Валленланд Вики
vlwiki
https://vl.skywiki.org/wiki/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0
MediaWiki 1.43.1
first-letter
Медиа
Служебная
Обсуждение
Участник
Обсуждение участника
Валленланд Вики
Валленланд Вики talk
Файл
Обсуждение файла
MediaWiki
Обсуждение MediaWiki
Шаблон
Обсуждение шаблона
Справка
Обсуждение справки
Категория
Обсуждение категории
GeoJson
GeoJson talk
Campaign
Campaign talk
Модуль
Обсуждение модуля
Шаблон:Флагификация/Великобритания
10
71
139
2010-05-18T20:27:18Z
wikipedia:ru>Rubinbot II
0
Защищена «[[Шаблон:Флагификация/Великобритания]]»: критический шаблон ([edit=sysop] (бессрочно) [move=sysop] (бессрочно))
wikitext
text/x-wiki
{{ {{{1<noinclude>|флагификация/флаг</noinclude>}}}
| alias = Великобритания
| flag alias = Flag of the United Kingdom.svg
| flag alias-1707 = Union flag 1606 (Kings Colors).svg
| flag alias-1658 = Flag of the Commonwealth (1658-1660).svg
| flag alias-1651 = Flag of The Commonwealth.svg
| flag alias-1649 = Flag of the Commonwealth (1649-1651).svg
| flag alias-1606 = Union flag 1606 (Kings Colors).svg
| flag alias-ВМС = Naval Ensign of the United Kingdom.svg
| flag alias-торговый = Civil Ensign of the United Kingdom.svg
| flag alias-ВВС = Ensign of the Royal Air Force.svg
| flag alias-дипломатический = Government Ensign of the United Kingdom.svg
| flag alias-армия = Flag of the British Army.svg
| variant = {{{variant|}}}
<noinclude>
| var1 = 1707
| var2 = 1658
| var3 = 1651
| var4 = 1649
| var5 = 1606
| var6 = ВМС
| var7 = торговый
| var8 = ВВС
| var9 = дипломатический
| var10 = армия
</noinclude>
| размер = {{{размер|}}}
}}
4bf44640a433c2a79fdf1d0e148897cad36f0f4d
Шаблон:Str len
10
75
147
2013-03-14T14:34:59Z
wikipedia:ru>DR
0
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke:String|len|s={{{1|}}}}}<noinclude>
{{doc}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
95f10258d5214440d2706952656564f216c2e4cc
Шаблон:Str rep
10
28
53
2015-02-28T09:38:11Z
wikipedia:ru>Rubinbot II
0
Защищена Шаблон:Str rep: Top used templates to be protected ([Редактирование=только администраторы] (бессрочно) [Переименование=только администраторы] (бессро
wikitext
text/x-wiki
<includeonly>{{{{{|safesubst:}}}#invoke:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|{{{4|1}}}}}</includeonly><noinclude>{{doc}}</noinclude>
c75032f150c372324c69a6f62ff4ab1492ad4cfa
Модуль:Namespace detect/data
828
22
41
2015-06-27T21:11:34Z
wikipedia:ru>Draa kul
0
Защищена Модуль:Namespace detect/data: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только администрато…
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Namespace detect data --
-- This module holds data for [[Module:Namespace detect]] to be loaded per --
-- page, rather than per #invoke, for performance reasons. --
--------------------------------------------------------------------------------
local cfg = require('Module:Namespace detect/config')
local function addKey(t, key, defaultKey)
if key ~= defaultKey then
t[#t + 1] = key
end
end
-- Get a table of parameters to query for each default parameter name.
-- This allows wikis to customise parameter names in the cfg table while
-- ensuring that default parameter names will always work. The cfg table
-- values can be added as a string, or as an array of strings.
local defaultKeys = {
'main',
'talk',
'other',
'subjectns',
'demospace',
'demopage'
}
local argKeys = {}
for i, defaultKey in ipairs(defaultKeys) do
argKeys[defaultKey] = {defaultKey}
end
for defaultKey, t in pairs(argKeys) do
local cfgValue = cfg[defaultKey]
local cfgValueType = type(cfgValue)
if cfgValueType == 'string' then
addKey(t, cfgValue, defaultKey)
elseif cfgValueType == 'table' then
for i, key in ipairs(cfgValue) do
addKey(t, key, defaultKey)
end
end
cfg[defaultKey] = nil -- Free the cfg value as we don't need it any more.
end
local function getParamMappings()
--[[
-- Returns a table of how parameter names map to namespace names. The keys
-- are the actual namespace names, in lower case, and the values are the
-- possible parameter names for that namespace, also in lower case. The
-- table entries are structured like this:
-- {
-- [''] = {'main'},
-- ['wikipedia'] = {'wikipedia', 'project', 'wp'},
-- ...
-- }
--]]
local mappings = {}
local mainNsName = mw.site.subjectNamespaces[0].name
mainNsName = mw.ustring.lower(mainNsName)
mappings[mainNsName] = mw.clone(argKeys.main)
mappings['talk'] = mw.clone(argKeys.talk)
for nsid, ns in pairs(mw.site.subjectNamespaces) do
if nsid ~= 0 then -- Exclude main namespace.
local nsname = mw.ustring.lower(ns.name)
local canonicalName = mw.ustring.lower(ns.canonicalName)
mappings[nsname] = {nsname}
if canonicalName ~= nsname then
table.insert(mappings[nsname], canonicalName)
end
for _, alias in ipairs(ns.aliases) do
table.insert(mappings[nsname], mw.ustring.lower(alias))
end
end
end
return mappings
end
return {
argKeys = argKeys,
cfg = cfg,
mappings = getParamMappings()
}
d224f42a258bc308ef3ad8cc8686cd7a4f47d005
Модуль:Namespace detect/config
828
23
43
2015-06-27T21:11:46Z
wikipedia:ru>Draa kul
0
Защищена Модуль:Namespace detect/config: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только администрат…
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Namespace detect configuration data --
-- --
-- This module stores configuration data for Module:Namespace detect. Here --
-- you can localise the module to your wiki's language. --
-- --
-- To activate a configuration item, you need to uncomment it. This means --
-- that you need to remove the text "-- " at the start of the line. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Parameter names --
-- These configuration items specify custom parameter names. Values added --
-- here will work in addition to the default English parameter names. --
-- To add one extra name, you can use this format: --
-- --
-- cfg.foo = 'parameter name' --
-- --
-- To add multiple names, you can use this format: --
-- --
-- cfg.foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'} --
--------------------------------------------------------------------------------
---- This parameter displays content for the main namespace:
-- cfg.main = 'main'
---- This parameter displays in talk namespaces:
-- cfg.talk = 'talk'
---- This parameter displays content for "other" namespaces (namespaces for which
---- parameters have not been specified):
-- cfg.other = 'other'
---- This parameter makes talk pages behave as though they are the corresponding
---- subject namespace. Note that this parameter is used with [[Module:Yesno]].
---- Edit that module to change the default values of "yes", "no", etc.
-- cfg.subjectns = 'subjectns'
---- This parameter sets a demonstration namespace:
-- cfg.demospace = 'demospace'
---- This parameter sets a specific page to compare:
cfg.demopage = 'page'
--------------------------------------------------------------------------------
-- Table configuration --
-- These configuration items allow customisation of the "table" function, --
-- used to generate a table of possible parameters in the module --
-- documentation. --
--------------------------------------------------------------------------------
---- The header for the namespace column in the wikitable containing the list of
---- possible subject-space parameters.
-- cfg.wikitableNamespaceHeader = 'Namespace'
---- The header for the wikitable containing the list of possible subject-space
---- parameters.
-- cfg.wikitableAliasesHeader = 'Aliases'
--------------------------------------------------------------------------------
-- End of configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line.
0e4ff08d13c4b664d66b32c232deb129b77c1a56
Модуль:Color contrast/colors
828
65
127
2016-06-19T09:05:16Z
wikipedia:ru>Dima st bk
0
Защищена Модуль:Color contrast/colors: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только администрато…
Scribunto
text/plain
return {
aliceblue = 0.92880068253475,
antiquewhite = 0.84646951707754,
aqua = 0.7874,
aquamarine = 0.8078549208338,
azure = 0.97265264954166,
beige = 0.8988459998705,
bisque = 0.80732327372979,
black = 0,
blanchedalmond = 0.85084439608156,
blue = 0.0722,
blueviolet = 0.12622014321946,
brown = 0.098224287876511,
burlywood = 0.51559844533893,
cadetblue = 0.29424681085422,
chartreuse = 0.76032025902623,
chocolate = 0.23898526114557,
coral = 0.37017930872924,
cornflowerblue = 0.30318641994179,
cornsilk = 0.93562110372965,
crimson = 0.16042199953026,
cyan = 0.7874,
darkblue = 0.018640801980939,
darkcyan = 0.20329317839046,
darkgoldenrod = 0.27264703559993,
darkgray = 0.39675523072563,
darkgreen = 0.091143429047575,
darkgrey = 0.39675523072563,
darkkhaki = 0.45747326349994,
darkmagenta = 0.07353047651207,
darkolivegreen = 0.12651920884889,
darkorange = 0.40016167026524,
darkorchid = 0.13413142174857,
darkred = 0.054889674531132,
darksalmon = 0.40541471563381,
darkseagreen = 0.43789249325969,
darkslateblue = 0.065792846227988,
darkslategray = 0.067608151928044,
darkslategrey = 0.067608151928044,
darkturquoise = 0.4874606277449,
darkviolet = 0.10999048339343,
deeppink = 0.23866895828276,
deepskyblue = 0.44481603395575,
dimgray = 0.14126329114027,
dimgrey = 0.14126329114027,
dodgerblue = 0.27442536991456,
firebrick = 0.10724525535015,
floralwhite = 0.95922484825004,
forestgreen = 0.18920812076002,
fuchsia = 0.2848,
gainsboro = 0.71569350050648,
ghostwhite = 0.94311261886323,
gold = 0.69860877428159,
goldenrod = 0.41919977809569,
gray = 0.2158605001139,
green = 0.15438342968146,
greenyellow = 0.80609472611453,
grey = 0.2158605001139,
honeydew = 0.96336535554782,
hotpink = 0.34658438169715,
indianred = 0.21406134963884,
indigo = 0.03107561486337,
ivory = 0.99071270600615,
khaki = 0.77012343394121,
lavender = 0.80318750514521,
lavenderblush = 0.90172748631046,
lawngreen = 0.73905893124963,
lemonchiffon = 0.94038992245622,
lightblue = 0.63709141280807,
lightcoral = 0.35522120733135,
lightcyan = 0.94587293494829,
lightgoldenrodyellow = 0.93348351018297,
lightgray = 0.65140563741982,
lightgreen = 0.69091979956865,
lightgrey = 0.65140563741982,
lightpink = 0.58566152734898,
lightsalmon = 0.4780675225206,
lightseagreen = 0.35050145117042,
lightskyblue = 0.56195637618331,
lightslategray = 0.23830165007287,
lightslategrey = 0.23830165007287,
lightsteelblue = 0.53983888284666,
lightyellow = 0.98161818392882,
lime = 0.7152,
limegreen = 0.44571042246098,
linen = 0.88357340984379,
magenta = 0.2848,
maroon = 0.045891942324215,
mediumaquamarine = 0.49389703310801,
mediumblue = 0.044077780212328,
mediumorchid = 0.21639251153773,
mediumpurple = 0.22905858091648,
mediumseagreen = 0.34393112338131,
mediumslateblue = 0.20284629471622,
mediumspringgreen = 0.70704308194184,
mediumturquoise = 0.5133827926448,
mediumvioletred = 0.14371899849357,
midnightblue = 0.02071786635086,
mintcream = 0.97834604947588,
mistyrose = 0.82183047859185,
moccasin = 0.80083000991567,
navajowhite = 0.76519682342785,
navy = 0.015585128108224,
oldlace = 0.91900633405549,
olive = 0.20027537200568,
olivedrab = 0.22593150951929,
orange = 0.4817026703631,
orangered = 0.25516243753416,
orchid = 0.31348806761439,
palegoldenrod = 0.78792647887614,
palegreen = 0.77936759006353,
paleturquoise = 0.76436077921714,
palevioletred = 0.28754994117889,
papayawhip = 0.87797100199835,
peachpuff = 0.74905589878251,
peru = 0.30113074877936,
pink = 0.63271070702466,
plum = 0.45734221587969,
powderblue = 0.68254586500605,
purple = 0.061477070432439,
rebeccapurple = 0.07492341159447,
red = 0.2126,
rosybrown = 0.32319457649407,
royalblue = 0.16663210743188,
saddlebrown = 0.097922285020521,
salmon = 0.36977241527596,
sandybrown = 0.46628543696283,
seagreen = 0.19734199706275,
seashell = 0.92737862206922,
sienna = 0.13697631337098,
silver = 0.52711512570581,
skyblue = 0.55291668518184,
slateblue = 0.14784278062136,
slategray = 0.20896704076536,
slategrey = 0.20896704076536,
snow = 0.96533341834849,
springgreen = 0.73052306068529,
steelblue = 0.20562642207625,
tan = 0.48237604163921,
teal = 0.16996855778968,
thistle = 0.56818401093733,
tomato = 0.30638612719415,
turquoise = 0.5895536427578,
violet = 0.40315452986676,
wheat = 0.74909702820482,
white = 1,
whitesmoke = 0.91309865179342,
yellow = 0.9278,
yellowgreen = 0.50762957208707,
}
6ae47fdb24de4eed5ec26d203faf5341a388987b
Шаблон:Wikidata/p570
10
47
91
2016-07-12T17:40:22Z
wikipedia:ru>Putnik
0
скрытие значения из Викиданных при помощи «-»
wikitext
text/x-wiki
{{#switch:{{{1|}}}|-=|={{#invoke:Wikidata|formatStatements|property=p570|claim-module=Wikidata/date|claim-function=formatDateOfDeathClaim|nocat={{{nocat|}}}{{NAMESPACE}}}}|{{#invoke:Infocards|dateOfDeath|{{{2|}}}|{{{1|}}}|nocat={{{nocat|}}}{{NAMESPACE}}}}}}<noinclude>{{doc}}</noinclude>
a51af6d007d156cfeacb13a0a4a7471da7d4ed22
Шаблон:Str find
10
52
101
2016-11-07T15:00:14Z
wikipedia:ru>Jack who built the house
0
последуем написанному в комментарии и перенесём категории на подстраницу
wikitext
text/x-wiki
{{ {{{|safesubst:}}}#invoke:String|str_find|source={{{1|}}}|{{{2|}}}}}<noinclude>
{{doc}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
18d1469d30d27a82ee15fd2fb1ca12a34b5f5e87
Шаблон:Nobr
10
48
93
2016-12-02T13:15:38Z
wikipedia:ru>Jack who built the house
0
используем класс nowrap
wikitext
text/x-wiki
<includeonly><span class="nowrap">{{{1}}}</span></includeonly><noinclude>
{{doc}}
<!-- Пожалуйста, добавляйте категории и интервики на страницу документации! -->
</noinclude>
989c6f164ed3a8543e916c8f1746ba1ab94fb068
Шаблон:Delink
10
38
73
2017-08-01T19:23:44Z
wikipedia:ru>Q-bit array
0
Защитил «[[Шаблон:Delink]]»: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только администраторы] (б…
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:delink|delink}}<noinclude>
{{doc}}
</noinclude>
dbac86e53b946e60d5b6236381e8c31858e79ee5
Шаблон:Карточка/имя
10
44
85
2017-08-01T19:26:40Z
wikipedia:ru>Q-bit array
0
Защитил «[[Шаблон:Карточка/имя]]»: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только админист…
wikitext
text/x-wiki
{{#if:{{{1|}}}|{{{1}}}|{{сначала имя|{{PAGENAME}}}}}}<noinclude>
{{doc}}
</noinclude>
c2c97d1196f5c50a2ec1aa866cd4004526a32383
Модуль:Category handler/config
828
19
35
2017-08-01T19:26:42Z
wikipedia:ru>Q-bit array
0
Защитил «[[Модуль:Category handler/config]]»: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только админист…
Scribunto
text/plain
--------------------------------------------------------------------------------
-- [[Module:Category handler]] configuration data --
-- Language-specific parameter names and values can be set here. --
-- For blacklist config, see [[Module:Category handler/blacklist]]. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Start configuration data --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Parameter names --
-- These configuration items specify custom parameter names. --
-- To add one extra name, you can use this format: --
-- --
-- foo = 'parameter name', --
-- --
-- To add multiple names, you can use this format: --
-- --
-- foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'}, --
--------------------------------------------------------------------------------
cfg.parameters = {
-- The nocat and categories parameter suppress
-- categorisation. They are used with Module:Yesno, and work as follows:
--
-- cfg.nocat:
-- Result of yesno() Effect
-- true Categorisation is suppressed
-- false Categorisation is allowed, and
-- the blacklist check is skipped
-- nil Categorisation is allowed
--
-- cfg.categories:
-- Result of yesno() Effect
-- true Categorisation is allowed, and
-- the blacklist check is skipped
-- false Categorisation is suppressed
-- nil Categorisation is allowed
nocat = 'nocat',
categories = 'categories',
-- The parameter name for the legacy "category2" parameter. This skips the
-- blacklist if set to the cfg.category2Yes value, and suppresses
-- categorisation if present but equal to anything other than
-- cfg.category2Yes or cfg.category2Negative.
category2 = 'category2',
-- cfg.subpage is the parameter name to specify how to behave on subpages.
subpage = 'subpage',
-- The parameter for data to return in all namespaces.
all = 'all',
-- The parameter name for data to return if no data is specified for the
-- namespace that is detected.
other = 'other',
-- The parameter name used to specify a page other than the current page;
-- used for testing and demonstration.
demopage = 'page',
}
--------------------------------------------------------------------------------
-- Parameter values --
-- These are set values that can be used with certain parameters. Only one --
-- value can be specified, like this: --
-- --
-- cfg.foo = 'value name' -- --
--------------------------------------------------------------------------------
-- The following settings are used with the cfg.category2 parameter. Setting
-- cfg.category2 to cfg.category2Yes skips the blacklist, and if cfg.category2
-- is present but equal to anything other than cfg.category2Yes or
-- cfg.category2Negative then it supresses cateogrisation.
cfg.category2Yes = 'yes'
cfg.category2Negative = '¬'
-- The following settings are used with the cfg.subpage parameter.
-- cfg.subpageNo is the value to specify to not categorise on subpages;
-- cfg.subpageOnly is the value to specify to only categorise on subpages.
cfg.subpageNo = 'no'
cfg.subpageOnly = 'only'
--------------------------------------------------------------------------------
-- Default namespaces --
-- This is a table of namespaces to categorise by default. The keys are the --
-- namespace numbers. --
--------------------------------------------------------------------------------
cfg.defaultNamespaces = {
[ 0] = true, -- main
[ 6] = true, -- file
[ 12] = true, -- help
[ 14] = true, -- category
[100] = true, -- portal
[108] = true, -- book
}
--------------------------------------------------------------------------------
-- Wrappers --
-- This is a wrapper template or a list of wrapper templates to be passed to --
-- [[Module:Arguments]]. --
--------------------------------------------------------------------------------
cfg.wrappers = 'Template:Category handler'
--------------------------------------------------------------------------------
-- End configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line.
373cd107b13a5b00e6a1b7e66a749f12502c849d
Модуль:Category handler/blacklist
828
21
39
2017-08-01T19:26:43Z
wikipedia:ru>Q-bit array
0
Защитил «[[Модуль:Category handler/blacklist]]»: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только админис…
Scribunto
text/plain
-- This module contains the blacklist used by [[Module:Category handler]].
-- Pages that match Lua patterns in this list will not be categorised unless
-- categorisation is explicitly requested.
return {
'^Main Page$', -- don't categorise the main page.
-- Don't categorise the following pages or their subpages.
-- "%f[/\0]" matches if the next character is "/" or the end of the string.
'^Wikipedia:Cascade%-protected items%f[/\0]',
'^User:UBX%f[/\0]', -- The userbox "template" space.
'^User talk:UBX%f[/\0]',
-- Don't categorise subpages of these pages, but allow
-- categorisation of the base page.
'^Wikipedia:Template messages/.*$',
'/[aA]rchive' -- Don't categorise archives.
}
c84948ad9808d5d323408d5d10d5652f748a0550
Модуль:Category handler
828
15
27
2017-08-01T19:26:45Z
wikipedia:ru>Q-bit array
0
Защитил «[[Модуль:Category handler]]»: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только администрато…
Scribunto
text/plain
--------------------------------------------------------------------------------
-- --
-- CATEGORY HANDLER --
-- --
-- This module implements the {{category handler}} template in Lua, --
-- with a few improvements: all namespaces and all namespace aliases --
-- are supported, and namespace names are detected automatically for --
-- the local wiki. This module requires [[Module:Namespace detect]] --
-- and [[Module:Yesno]] to be available on the local wiki. It can be --
-- configured for different wikis by altering the values in --
-- [[Module:Category handler/config]], and pages can be blacklisted --
-- from categorisation by using [[Module:Category handler/blacklist]]. --
-- --
--------------------------------------------------------------------------------
-- Load required modules
local yesno = require('Module:Yesno')
-- Lazily load things we don't always need
local mShared, mappings
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function trimWhitespace(s, removeBlanks)
if type(s) ~= 'string' then
return s
end
s = s:match('^%s*(.-)%s*$')
if removeBlanks then
if s ~= '' then
return s
else
return nil
end
else
return s
end
end
--------------------------------------------------------------------------------
-- CategoryHandler class
--------------------------------------------------------------------------------
local CategoryHandler = {}
CategoryHandler.__index = CategoryHandler
function CategoryHandler.new(data, args)
local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)
-- Set the title object
do
local pagename = obj:parameter('demopage')
local success, titleObj
if pagename then
success, titleObj = pcall(mw.title.new, pagename)
end
if success and titleObj then
obj.title = titleObj
if titleObj == mw.title.getCurrentTitle() then
obj._usesCurrentTitle = true
end
else
obj.title = mw.title.getCurrentTitle()
obj._usesCurrentTitle = true
end
end
-- Set suppression parameter values
for _, key in ipairs{'nocat', 'categories'} do
local value = obj:parameter(key)
value = trimWhitespace(value, true)
obj['_' .. key] = yesno(value)
end
do
local subpage = obj:parameter('subpage')
local category2 = obj:parameter('category2')
if type(subpage) == 'string' then
subpage = mw.ustring.lower(subpage)
end
if type(category2) == 'string' then
subpage = mw.ustring.lower(category2)
end
obj._subpage = trimWhitespace(subpage, true)
obj._category2 = trimWhitespace(category2) -- don't remove blank values
end
return obj
end
function CategoryHandler:parameter(key)
local parameterNames = self._data.parameters[key]
local pntype = type(parameterNames)
if pntype == 'string' or pntype == 'number' then
return self._args[parameterNames]
elseif pntype == 'table' then
for _, name in ipairs(parameterNames) do
local value = self._args[name]
if value ~= nil then
return value
end
end
return nil
else
error(string.format(
'invalid config key "%s"',
tostring(key)
), 2)
end
end
function CategoryHandler:isSuppressedByArguments()
return
-- See if a category suppression argument has been set.
self._nocat == true
or self._categories == false
or (
self._category2
and self._category2 ~= self._data.category2Yes
and self._category2 ~= self._data.category2Negative
)
-- Check whether we are on a subpage, and see if categories are
-- suppressed based on our subpage status.
or self._subpage == self._data.subpageNo and self.title.isSubpage
or self._subpage == self._data.subpageOnly and not self.title.isSubpage
end
function CategoryHandler:shouldSkipBlacklistCheck()
-- Check whether the category suppression arguments indicate we
-- should skip the blacklist check.
return self._nocat == false
or self._categories == true
or self._category2 == self._data.category2Yes
end
function CategoryHandler:matchesBlacklist()
if self._usesCurrentTitle then
return self._data.currentTitleMatchesBlacklist
else
mShared = mShared or require('Module:Category handler/shared')
return mShared.matchesBlacklist(
self.title.prefixedText,
mw.loadData('Module:Category handler/blacklist')
)
end
end
function CategoryHandler:isSuppressed()
-- Find if categories are suppressed by either the arguments or by
-- matching the blacklist.
return self:isSuppressedByArguments()
or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()
end
function CategoryHandler:getNamespaceParameters()
if self._usesCurrentTitle then
return self._data.currentTitleNamespaceParameters
else
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
return mShared.getNamespaceParameters(
self.title,
mappings
)
end
end
function CategoryHandler:namespaceParametersExist()
-- Find whether any namespace parameters have been specified.
-- We use the order "all" --> namespace params --> "other" as this is what
-- the old template did.
if self:parameter('all') then
return true
end
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
for ns, params in pairs(mappings) do
for i, param in ipairs(params) do
if self._args[param] then
return true
end
end
end
if self:parameter('other') then
return true
end
return false
end
function CategoryHandler:getCategories()
local params = self:getNamespaceParameters()
local nsCategory
for i, param in ipairs(params) do
local value = self._args[param]
if value ~= nil then
nsCategory = value
break
end
end
if nsCategory ~= nil or self:namespaceParametersExist() then
-- Namespace parameters exist - advanced usage.
if nsCategory == nil then
nsCategory = self:parameter('other')
end
local ret = {self:parameter('all')}
local numParam = tonumber(nsCategory)
if numParam and numParam >= 1 and math.floor(numParam) == numParam then
-- nsCategory is an integer
ret[#ret + 1] = self._args[numParam]
else
ret[#ret + 1] = nsCategory
end
if #ret < 1 then
return nil
else
return table.concat(ret)
end
elseif self._data.defaultNamespaces[self.title.namespace] then
-- Namespace parameters don't exist, simple usage.
return self._args[1]
end
return nil
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
-- Used for testing purposes.
return {
CategoryHandler = CategoryHandler
}
end
function p._main(args, data)
data = data or mw.loadData('Module:Category handler/data')
local handler = CategoryHandler.new(data, args)
if handler:isSuppressed() then
return nil
end
return handler:getCategories()
end
function p.main(frame, data)
data = data or mw.loadData('Module:Category handler/data')
local args = require('Module:Arguments').getArgs(frame, {
wrappers = data.wrappers,
valueFunc = function (k, v)
v = trimWhitespace(v)
if type(k) == 'number' then
if v ~= '' then
return v
else
return nil
end
else
return v
end
end
})
return p._main(args, data)
end
return p
b74dd63857b24904ac452429b11213f18647471f
Модуль:Category handler/shared
828
20
37
2017-08-01T19:26:47Z
wikipedia:ru>Q-bit array
0
Защитил «[[Модуль:Category handler/shared]]»: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только админист…
Scribunto
text/plain
-- This module contains shared functions used by [[Module:Category handler]]
-- and its submodules.
local p = {}
function p.matchesBlacklist(page, blacklist)
for i, pattern in ipairs(blacklist) do
local match = mw.ustring.match(page, pattern)
if match then
return true
end
end
return false
end
function p.getParamMappings(useLoadData)
local dataPage = 'Module:Namespace detect/data'
if useLoadData then
return mw.loadData(dataPage).mappings
else
return require(dataPage).mappings
end
end
function p.getNamespaceParameters(titleObj, mappings)
-- We don't use title.nsText for the namespace name because it adds
-- underscores.
local mappingsKey
if titleObj.isTalkPage then
mappingsKey = 'talk'
else
mappingsKey = mw.site.namespaces[titleObj.namespace].name
end
mappingsKey = mw.ustring.lower(mappingsKey)
return mappings[mappingsKey] or {}
end
return p
d2d5de1a031e6ce97c242cbfa8afe7a92cb9eca5
Модуль:Category handler/data
828
18
33
2017-08-01T19:26:49Z
wikipedia:ru>Q-bit array
0
Защитил «[[Модуль:Category handler/data]]»: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только администр…
Scribunto
text/plain
-- This module assembles data to be passed to [[Module:Category handler]] using
-- mw.loadData. This includes the configuration data and whether the current
-- page matches the title blacklist.
local data = require('Module:Category handler/config')
local mShared = require('Module:Category handler/shared')
local blacklist = require('Module:Category handler/blacklist')
local title = mw.title.getCurrentTitle()
data.currentTitleMatchesBlacklist = mShared.matchesBlacklist(
title.prefixedText,
blacklist
)
data.currentTitleNamespaceParameters = mShared.getNamespaceParameters(
title,
mShared.getParamMappings()
)
return data
abbc68048ff698e88dda06b64ecf384bbf583120
Шаблон:Yesno
10
25
47
2017-08-01T19:30:50Z
wikipedia:ru>Q-bit array
0
Защитил «[[Шаблон:Yesno]]»: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только администраторы] (бе…
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#switch: {{<includeonly>safesubst:</includeonly>lc: {{{1|¬}}} }}
|no
|n
|нет
|false
|0 = {{{no|<!-- null -->}}}
| = {{{blank|{{{no|<!-- null -->}}}}}}
|¬ = {{{¬|}}}
|yes
|y
|да
|true
|1 = {{{yes|yes}}}
|#default = {{{def|{{{yes|yes}}}}}}
}}<noinclude>
{{Documentation}}
</noinclude>
4e236854c477d07a225c2ab6c016c389b133e8d3
Модуль:Wikidata:Dictionary/P424
828
81
159
2017-08-01T19:32:01Z
wikipedia:ru>Q-bit array
0
Защитил «[[Модуль:Wikidata:Dictionary/P424]]»: критический шаблон ([Редактирование=только администраторы] (бессрочно) [Переименование=только админист…
Scribunto
text/plain
return {
Q143={'eo'},
Q150={'fr'},
Q188={'de'},
Q256={'tr'},
Q294={'is'},
Q328={'en'},
Q397={'la'},
Q652={'it'},
Q809={'pl'},
Q1321={'es'},
Q1412={'fi'},
Q1568={'hi'},
Q1571={'mr'},
Q1617={'ur'},
Q1860={'en'},
Q4627={'ay'},
Q5111={'ab'},
Q5137={'gu'},
Q5146={'pt'},
Q5218={'qu'},
Q5287={'ja'},
Q5885={'ta'},
Q6654={'hr'},
Q7026={'ca'},
Q7411={'nl'},
Q7737={'ru'},
Q7838={'sw'},
Q7850={'zh'},
Q7913={'ro'},
Q7918={'bg'},
Q7930={'mg'},
Q7979={'en-gb'},
Q8097={'te'},
Q8108={'ka'},
Q8447={'fr'},
Q8449={'es'},
Q8641={'yi'},
Q8748={'sq'},
Q8752={'eu'},
Q8765={'an'},
Q8785={'hy'},
Q8798={'uk'},
Q9027={'sv'},
Q9035={'da'},
Q9043={'no'},
Q9051={'lb'},
Q9056={'cs'},
Q9058={'sk'},
Q9063={'sl'},
Q9067={'hu'},
Q9072={'et'},
Q9078={'lv'},
Q9083={'lt'},
Q9091={'be'},
Q9129={'mis'},
Q9142={'ga'},
Q9166={'mt'},
Q9168={'fa'},
Q9176={'ko'},
Q9186={'zh-yue','yue'},
Q9199={'vi'},
Q9205={'km'},
Q9211={'lo'},
Q9217={'th'},
Q9228={'my'},
Q9237={'ms'},
Q9240={'id'},
Q9246={'mn'},
Q9252={'kk'},
Q9255={'ky'},
Q9260={'tg'},
Q9264={'uz'},
Q9267={'tk'},
Q9288={'he'},
Q9292={'az'},
Q9296={'mk'},
Q9299={'sr'},
Q9301={'sh'},
Q9303={'bs'},
Q9307={'gl'},
Q9309={'cy'},
Q9314={'gd'},
Q9610={'bn'},
Q10000={'nl'},
Q10134={'tlh'},
Q10179={'zu'},
Q10199={'diq'},
Q11059={'sa'},
Q11913={'bg'},
Q11918={'el'},
Q11920={'it'},
Q11921={'pt'},
Q12107={'br'},
Q12175={'gv'},
Q12237={'la'},
Q13198={'rcf'},
Q13199={'rm'},
Q13201={'rmy'},
Q13216={'za'},
Q13218={'xh'},
Q13238={'udm'},
Q13248={'hsb'},
Q13263={'ug'},
Q13267={'si'},
Q13275={'so'},
Q13286={'dsb'},
Q13293={'sma'},
Q13300={'nah'},
Q13307={'na'},
Q13310={'nv'},
Q13324={'min'},
Q13330={'mwl'},
Q13343={'mdf'},
Q13356={'mzn'},
Q13357={'fit'},
Q13358={'ruq'},
Q13359={'xmf'},
Q13389={'ba'},
Q13955={'ar'},
Q14185={'oc'},
Q14196={'af'},
Q14380={'sl'},
Q14549={'sco'},
Q15085={'pms'},
Q15087={'frp'},
Q17985={'ko'},
Q21117={'esu'},
Q22711={'pdc'},
Q23014={'pfl'},
Q25164={'nn'},
Q25167={'nb'},
Q25258={'fo'},
Q25285={'tt'},
Q25289={'kw'},
Q25355={'kl'},
Q25433={'nds'},
Q26245={'rue'},
Q27154={'stq'},
Q27175={'fy'},
Q27183={'ik'},
Q27683={'ace'},
Q27776={'ady'},
Q27811={'aa'},
Q28026={'ak'},
Q28224={'frr'},
Q28244={'am'},
Q28378={'anp'},
Q28602={'arc'},
Q29316={'roa-rup','rup'},
Q29401={'as'},
Q29507={'ast'},
Q29540={'bar'},
Q29561={'av'},
Q29919={'arz'},
Q29921={'iu'},
Q29952={'myv'},
Q30005={'ee'},
Q30007={'ext'},
Q30239={'zh'},
Q30319={'szl'},
Q31746={'lez'},
Q32145={'ksh'},
Q32641={'mis'},
Q32656={'dv'},
Q32704={'ve'},
Q32724={'vec'},
Q32747={'vep'},
Q32762={'fiu-vro','vro'},
Q32858={'vot'},
Q32979={'cho'},
Q33025={'bej'},
Q33081={'dz'},
Q33111={'co'},
Q33120={'bxr'},
Q33151={'bjn'},
Q33170={'ckt'},
Q33190={'bug'},
Q33202={'brh'},
Q33219={'map-bms'},
Q33239={'ceb'},
Q33243={'bm'},
Q33262={'ch'},
Q33265={'chy'},
Q33268={'bh','bho'},
Q33273={'ny'},
Q33281={'cbk-zam'},
Q33284={'bcl'},
Q33287={'gaa'},
Q33291={'fon'},
Q33295={'fj'},
Q33315={'hz'},
Q33348={'cv'},
Q33350={'ce'},
Q33357={'crh'},
Q33368={'lg'},
Q33375={'hak'},
Q33388={'chr'},
Q33390={'cr'},
Q33441={'fur'},
Q33454={'ff'},
Q33457={'gag'},
Q33475={'gan'},
Q33491={'ht'},
Q33509={'inh'},
Q33522={'kbd'},
Q33541={'kaa'},
Q33549={'jv'},
Q33552={'ks'},
Q33569={'haw'},
Q33573={'rw'},
Q33578={'ig'},
Q33583={'rn'},
Q33587={'ki'},
Q33617={'ho'},
Q33634={'xal'},
Q33657={'glk'},
Q33661={'mfe'},
Q33673={'kn'},
Q33690={'csb'},
Q33698={'liv'},
Q33702={'kg'},
Q33714={'krc'},
Q33720={'krj'},
Q33730={'arn'},
Q33754={'lmo'},
Q33786={'sid'},
Q33810={'or'},
Q33823={'ne'},
Q33845={'nap'},
Q33850={'nrm'},
Q33856={'pap'},
Q33864={'om'},
Q33879={'pag'},
Q33900={'ng'},
Q33947={'se'},
Q33954={'sg'},
Q33968={'os'},
Q33973={'scn'},
Q33976={'sc'},
Q33979={'new'},
Q33989={'srn'},
Q33997={'sd'},
Q34002={'su'},
Q34004={'sn'},
Q34011={'sm'},
Q34014={'ss'},
Q34015={'crs'},
Q34024={'pcd'},
Q34055={'tvl'},
Q34057={'tl'},
Q34094={'to'},
Q34119={'tyv'},
Q34124={'ti'},
Q34125={'tet'},
Q34128={'ty'},
Q34137={'tn'},
Q34138={'tum'},
Q34147={'vls'},
Q34159={'tpi'},
Q34208={'wbl'},
Q34219={'wa'},
Q34233={'ryu'},
Q34235={'ii'},
Q34247={'yai'},
Q34251={'tcy'},
Q34257={'wo'},
Q34271={'bo'},
Q34279={'war'},
Q34290={'wuu'},
Q34299={'sah'},
Q34311={'yo'},
Q34318={'tly'},
Q34327={'ts'},
Q34340={'st'},
Q35224={'io'},
Q35225={'peo'},
Q35452={'bi'},
Q35497={'grc'},
Q35499={'cu'},
Q35501={'prg'},
Q35722={'got'},
Q35744={'kri'},
Q35850={'ie'},
Q35853={'kab'},
Q35876={'gn'},
Q35934={'ia'},
Q35936={'ilo'},
Q35939={'jam'},
Q35963={'mis'},
Q35978={'hil'},
Q36094={'kr'},
Q36106={'lij'},
Q36109={'mai'},
Q36121={'pam'},
Q36126={'kv'},
Q36196={'lad'},
Q36206={'lbe'},
Q36212={'ltg'},
Q36217={'ln'},
Q36236={'ml'},
Q36280={'mh'},
Q36323={'pko'},
Q36350={'jbo'},
Q36368={'ku'},
Q36387={'mis'},
Q36392={'mo'},
Q36451={'mi'},
Q36455={'cdo'},
Q36495={'zh-min-nan','nan'},
Q36510={'el'},
Q36584={'olo'},
Q36699={'pis'},
Q36727={'pi'},
Q36730={'ota'},
Q36738={'nov'},
Q36748={'pnt'},
Q36811={'ckb'},
Q36850={'tw'},
Q36986={'vo'},
Q37041={'zh-classical','lzh'},
Q37059={'bpy'},
Q37178={'ine'},
Q38288={'diq'},
Q42365={'ang'},
Q44676={'en-ca'},
Q45041={'lez'},
Q46728={'hif'},
Q48183={'de'},
Q48952={'fa'},
Q53464={'hu'},
Q56240={'aeb'},
Q56318={'koi'},
Q56426={'ary'},
Q56475={'ha'},
Q56483={'lki'},
Q56499={'arq'},
Q56508={'sou'},
Q58172={'kk'},
Q58209={'ba'},
Q58215={'cv'},
Q58251={'az'},
Q58255={'tr'},
Q58635={'pa'},
Q58679={'sh'},
Q58680={'ps'},
Q58781={'rue'},
Q60786={'crh'},
Q60799={'ky'},
Q60819={'tt'},
Q60856={'ug'},
Q79633={'gag'},
Q79636={'kaa'},
Q102172={'li'},
Q131339={'als','gsw'},
Q146803={'lfn'},
Q155214={'id'},
Q169514={'sv'},
Q175482={'fi'},
Q177837={'ja'},
Q181037={'aln'},
Q181163={'da'},
Q182695={'mis'},
Q190551={'eo'},
Q191168={'cs'},
Q191769={'no'},
Q192582={'sk'},
Q199693={'ca'},
Q199698={'uk'},
Q199700={'ar'},
Q199864={'ro'},
Q199913={'he'},
Q200060={'et'},
Q200180={'vi'},
Q200183={'simple'},
Q200386={'sr','sr-ec','sr-el'},
Q202472={'lt'},
Q203488={'hr'},
Q206855={'ru'},
Q207260={'eu'},
Q208533={'sq'},
Q213434={'bat-smg','sgs'},
Q221444={'udm'},
Q225594={'sah'},
Q226150={'os'},
Q237409={'zea'},
Q242648={'eml'},
Q257829={'bqi'},
Q306626={'de-at'},
Q427715={'bn'},
Q497345={'vmf'},
Q511754={'tk'},
Q516137={'nds-nl'},
Q523014={'mus'},
Q547271={'cu'},
Q565074={'th'},
Q571001={'tpi'},
Q588620={'pam'},
Q595628={'oc'},
Q695526={'roa-tara'},
Q714826={'vo'},
Q718394={'is'},
Q722040={'hi'},
Q722243={'sw'},
Q728945={'lv'},
Q750553={'pt-br'},
Q766705={'af'},
Q824297={'mhr'},
Q837615={'ceb'},
Q841208={'gl'},
Q842341={'mk'},
Q844491={'ta'},
Q845993={'ms'},
Q846630={'cdo'},
Q846871={'br'},
Q848046={'te'},
Q848525={'cy'},
Q848974={'ka'},
Q856881={'myv'},
Q874555={'ml'},
Q875631={'ga'},
Q877583={'be'},
Q877685={'tl'},
Q880301={'frc'},
Q925661={'kv'},
Q928808={'dv'},
Q938216={'khw'},
Q940309={'szl'},
Q950058={'lb'},
Q966609={'su'},
Q1034940={'mrj'},
Q1047829={'bs'},
Q1047851={'nap'},
Q1055841={'vec'},
Q1058430={'scn'},
Q1066461={'ht'},
Q1067878={'ur'},
Q1071918={'ast'},
Q1110233={'wuu'},
Q1116066={'koi'},
Q1132977={'wa'},
Q1147071={'an'},
Q1148240={'yo'},
Q1154741={'ku'},
Q1154766={'io'},
Q1178461={'mdf'},
Q1190962={'zh-yue'},
Q1194341={'ru-sib'},
Q1211233={'als'},
Q1249553={'krc'},
Q1287192={'bpy'},
Q1291627={'new'},
Q1366643={'de-ch'},
Q1377618={'qu'},
Q1378484={'zh-classical'},
Q1389492={'pnb'},
Q1405077={'kj'},
Q1444686={'sco'},
};
c8444b1c598748668639bce6aaadca710aea0059
Модуль:URL
828
40
77
2017-09-18T16:34:08Z
wikipedia:ru>Jack who built the house
0
уточнение категоризации
Scribunto
text/plain
function startsWith( source, substring )
if mw.ustring.len( substring ) > mw.ustring.len( source ) then
return false
end
return mw.ustring.sub( source, 1, mw.ustring.len( substring ) ) == substring
end
p = {}
function formatUrlImpl( source, title, length )
local scheme, host, path
local postfix = ''
local arg1, arg2 = source, title
local isTestPage = mw.title.getCurrentTitle().prefixedText == 'Модуль:URL'
-- Две квадратные скобки подряд — [[вики-ссылка]] вместо [ссылки] — возвращаем вход как есть.
if string.find( arg1, "[[", 1, true ) then
local result = arg1
if not isTestPage then
result = result .. '[[Категория:Википедия:Статьи с вики-ссылкой, переданной в Модуль:URL]]'
if arg2 then
-- Если есть arg2, а мы распарсить ссылку не смогли, и значит заменить title не сможем корректно, это есть ошибка.
result = result .. '[[Категория:Википедия:Статьи с ошибочной работой Модуль:URL]]'
end
end
return result
end
-- Более одной квадратной скобки — скорее всего, задано более одного URL — тоже возвращаем как есть.
if select(2, string.gsub( arg1, "%[", "" )) > 1 then
local result = arg1
if not isTestPage then
result = result .. '[[Категория:Википедия:Статьи со сложным входом в Модуль:URL]]'
if arg2 then
-- Если есть arg2, а мы распарсить ссылку не смогли, и значит заменить title не сможем корректно, это есть ошибка.
result = result .. '[[Категория:Википедия:Статьи с ошибочной работой Модуль:URL]]'
end
end
return result
end
source = mw.text.trim( source, "%[%] " )
local titleDelimeterPosition = mw.ustring.find( source, " ", 1 )
if titleDelimeterPosition then
if not title or title == "" then
title = mw.ustring.sub( source, titleDelimeterPosition + 1 )
local postfixDelimeterPosition = mw.ustring.find( title, "%]", 1 )
if postfixDelimeterPosition then
postfix = mw.ustring.sub( title, postfixDelimeterPosition + 1 )
title = mw.ustring.sub( title, 1, postfixDelimeterPosition - 1 )
end
end
source = mw.ustring.sub( source, 1, titleDelimeterPosition - 1 )
end
local hostStartPosition
local schemeDelimeterPosition = mw.ustring.find( source, "://", 1, true )
if schemeDelimeterPosition then
scheme = mw.ustring.sub( source, 1, schemeDelimeterPosition + 2)
hostStartPosition = schemeDelimeterPosition + 3
elseif mw.ustring.find( source, "^//", 1 ) then
scheme = "//"
hostStartPosition = 3
elseif mw.ustring.find( source, "^mailto:", 1 ) then
scheme = "mailto:"
hostStartPosition = 8
elseif mw.ustring.find( source, "@", 1 ) then
scheme = "mailto:"
source = scheme .. source
hostStartPosition = 8
else
scheme = "http://"
source = scheme .. source
hostStartPosition = 8
end
if title then
local finds = mw.ustring.find( arg1, "[", 1, true )
if titleDelimeterPosition and finds and finds > titleDelimeterPosition + 1 then
-- Если titleDelimeterPosition промазал мимо скобки и нашел пробел раньше неё, к примеру "a [b c]",
-- то свернуть всю нашу хиромантию и выдать первый аргумент без изменений.
if arg2 == nil then
return arg1 .. (isTestPage and '' or '[[Категория:Википедия:Статьи со сложным входом в Модуль:URL]]')
-- Если есть arg2, а мы распарсить ссылку не смогли, и значит заменить title не сможем корректно, это есть ошибка.
-- С другой стороны, если arg2 нет, а arg1 очень сложный, то возможно это нормальный ход вещей,
-- и на вход в модуль дана уже очень сильно оформленная ссылка.
else
return arg1 .. (isTestPage and '' or '[[Категория:Википедия:Статьи с ошибочной работой Модуль:URL]]')
end
end
return '[' .. source .. ' ' .. title .. ']' .. postfix
end
local hostDelimeterPosition = mw.ustring.find( source, "/", hostStartPosition, true )
if hostDelimeterPosition then
host = mw.ustring.sub( source, hostStartPosition, hostDelimeterPosition - 1 )
if hostDelimeterPosition == mw.ustring.len( source ) then
path = nil
else
path = mw.ustring.sub( source, hostDelimeterPosition + 1 )
end
else
host = mw.ustring.sub( source, hostStartPosition )
end
-- post-split format options
if startsWith( host, 'www.' ) then
host = mw.ustring.sub( host, 5 )
end
host = mw.language.new( 'en' ):lc( host )
if path and path ~= '' and path ~= '/' then
local title = host .. '/' .. path
if length and #title > length then
title = host .. '/' .. mw.ustring.sub( path, 1, length - #title - 2 ) .. '…'
end
return '[' .. source .. ' ' .. title .. ']' .. postfix
else
return '[' .. source .. ' ' .. host .. ']' .. postfix
end
end
function p.formatUrl( frame )
local url = frame.args[1] or ''
local title = frame.args[2] or ''
local length = frame.args['length'] and tonumber( frame.args['length'] )
url = mw.text.trim( url )
title = mw.text.trim( title )
if url == '' then
return nil
end
if title == '' then
title = nil
end
return formatUrlImpl( url, title, length )
end
function p.formatUrlSingle( context, options, url )
url = mw.text.trim( url )
if url == '' then
return nil
end
local title = nil
if ( options['text'] and options['text'] ~= '' ) then
title = options['text']
end
local length = options['length'] and tonumber( options['length'] )
return formatUrlImpl( url, title, length )
end
return p
a991f879e135a472238c7f589e8d20d92a856d4d
Шаблон:Langi
10
7
11
2017-10-14T07:25:47Z
wikipedia:ru>Jack who built the house
0
→ [[/doc]]
wikitext
text/x-wiki
<span lang="{{{1}}}" xml:lang="{{{1}}}" style="font-style:italic;">{{{2}}}</span><noinclude>{{doc}}</noinclude>
7bb9f9098c88e770b982402adf30a3bbf645aa4b
Шаблон:Lang-de
10
80
157
2017-12-10T06:47:23Z
wikipedia:ru>Dima st bk
0
langi
wikitext
text/x-wiki
[[Немецкий язык|нем.]] {{langi|de|{{{1}}}}}<noinclude>{{doc|Lang/doc}}</noinclude>
646eff5eb102894e6474a9c639b707a8ea39dc6e
Модуль:Arguments
828
8
13
2018-01-12T21:01:04Z
wikipedia:ru>Grain of sand
0
sandbox → песочница
Scribunto
text/plain
-- This module provides easy processing of arguments passed to Scribunto from
-- #invoke. It is intended for use by other Lua modules, and should not be
-- called from #invoke directly.
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local arguments = {}
-- Generate four different tidyVal functions, so that we don't have to check the
-- options every time we call it.
local function tidyValDefault(key, val)
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val == '' then
return nil
else
return val
end
else
return val
end
end
local function tidyValTrimOnly(key, val)
if type(val) == 'string' then
return val:match('^%s*(.-)%s*$')
else
return val
end
end
local function tidyValRemoveBlanksOnly(key, val)
if type(val) == 'string' then
if val:find('%S') then
return val
else
return nil
end
else
return val
end
end
local function tidyValNoChange(key, val)
return val
end
local function matchesTitle(given, title)
local tp = type( given )
return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title
end
local translate_mt = { __index = function(t, k) return k end }
function arguments.getArgs(frame, options)
checkType('getArgs', 1, frame, 'table', true)
checkType('getArgs', 2, options, 'table', true)
frame = frame or {}
options = options or {}
--[[
-- Set up argument translation.
--]]
options.translate = options.translate or {}
if getmetatable(options.translate) == nil then
setmetatable(options.translate, translate_mt)
end
if options.backtranslate == nil then
options.backtranslate = {}
for k,v in pairs(options.translate) do
options.backtranslate[v] = k
end
end
if options.backtranslate and getmetatable(options.backtranslate) == nil then
setmetatable(options.backtranslate, {
__index = function(t, k)
if options.translate[k] ~= k then
return nil
else
return k
end
end
})
end
--[[
-- Get the argument tables. If we were passed a valid frame object, get the
-- frame arguments (fargs) and the parent frame arguments (pargs), depending
-- on the options set and on the parent frame's availability. If we weren't
-- passed a valid frame object, we are being called from another Lua module
-- or from the debug console, so assume that we were passed a table of args
-- directly, and assign it to a new variable (luaArgs).
--]]
local fargs, pargs, luaArgs
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then
if options.wrappers then
--[[
-- The wrappers option makes Module:Arguments look up arguments in
-- either the frame argument table or the parent argument table, but
-- not both. This means that users can use either the #invoke syntax
-- or a wrapper template without the loss of performance associated
-- with looking arguments up in both the frame and the parent frame.
-- Module:Arguments will look up arguments in the parent frame
-- if it finds the parent frame's title in options.wrapper;
-- otherwise it will look up arguments in the frame object passed
-- to getArgs.
--]]
local parent = frame:getParent()
if not parent then
fargs = frame.args
else
local title = parent:getTitle():gsub('/песочница$', '')
local found = false
if matchesTitle(options.wrappers, title) then
found = true
elseif type(options.wrappers) == 'table' then
for _,v in pairs(options.wrappers) do
if matchesTitle(v, title) then
found = true
break
end
end
end
-- We test for false specifically here so that nil (the default) acts like true.
if found or options.frameOnly == false then
pargs = parent.args
end
if not found or options.parentOnly == false then
fargs = frame.args
end
end
else
-- options.wrapper isn't set, so check the other options.
if not options.parentOnly then
fargs = frame.args
end
if not options.frameOnly then
local parent = frame:getParent()
pargs = parent and parent.args or nil
end
end
if options.parentFirst then
fargs, pargs = pargs, fargs
end
else
luaArgs = frame
end
-- Set the order of precedence of the argument tables. If the variables are
-- nil, nothing will be added to the table, which is how we avoid clashes
-- between the frame/parent args and the Lua args.
local argTables = {fargs}
argTables[#argTables + 1] = pargs
argTables[#argTables + 1] = luaArgs
--[[
-- Generate the tidyVal function. If it has been specified by the user, we
-- use that; if not, we choose one of four functions depending on the
-- options chosen. This is so that we don't have to call the options table
-- every time the function is called.
--]]
local tidyVal = options.valueFunc
if tidyVal then
if type(tidyVal) ~= 'function' then
error(
"bad value assigned to option 'valueFunc'"
.. '(function expected, got '
.. type(tidyVal)
.. ')',
2
)
end
elseif options.trim ~= false then
if options.removeBlanks ~= false then
tidyVal = tidyValDefault
else
tidyVal = tidyValTrimOnly
end
else
if options.removeBlanks ~= false then
tidyVal = tidyValRemoveBlanksOnly
else
tidyVal = tidyValNoChange
end
end
--[[
-- Set up the args, metaArgs and nilArgs tables. args will be the one
-- accessed from functions, and metaArgs will hold the actual arguments. Nil
-- arguments are memoized in nilArgs, and the metatable connects all of them
-- together.
--]]
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}
setmetatable(args, metatable)
local function mergeArgs(tables)
--[[
-- Accepts multiple tables as input and merges their keys and values
-- into one table. If a value is already present it is not overwritten;
-- tables listed earlier have precedence. We are also memoizing nil
-- values, which can be overwritten if they are 's' (soft).
--]]
for _, t in ipairs(tables) do
for key, val in pairs(t) do
if metaArgs[key] == nil and nilArgs[key] ~= 'h' then
local tidiedVal = tidyVal(key, val)
if tidiedVal == nil then
nilArgs[key] = 's'
else
metaArgs[key] = tidiedVal
end
end
end
end
end
--[[
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,
-- and are only fetched from the argument tables once. Fetching arguments
-- from the argument tables is the most resource-intensive step in this
-- module, so we try and avoid it where possible. For this reason, nil
-- arguments are also memoized, in the nilArgs table. Also, we keep a record
-- in the metatable of when pairs and ipairs have been called, so we do not
-- run pairs and ipairs on the argument tables more than once. We also do
-- not run ipairs on fargs and pargs if pairs has already been run, as all
-- the arguments will already have been copied over.
--]]
metatable.__index = function (t, key)
--[[
-- Fetches an argument when the args table is indexed. First we check
-- to see if the value is memoized, and if not we try and fetch it from
-- the argument tables. When we check memoization, we need to check
-- metaArgs before nilArgs, as both can be non-nil at the same time.
-- If the argument is not present in metaArgs, we also check whether
-- pairs has been run yet. If pairs has already been run, we return nil.
-- This is because all the arguments will have already been copied into
-- metaArgs by the mergeArgs function, meaning that any other arguments
-- must be nil.
--]]
if type(key) == 'string' then
key = options.translate[key]
end
local val = metaArgs[key]
if val ~= nil then
return val
elseif metatable.donePairs or nilArgs[key] then
return nil
end
for _, argTable in ipairs(argTables) do
local argTableVal = tidyVal(key, argTable[key])
if argTableVal ~= nil then
metaArgs[key] = argTableVal
return argTableVal
end
end
nilArgs[key] = 'h'
return nil
end
metatable.__newindex = function (t, key, val)
-- This function is called when a module tries to add a new value to the
-- args table, or tries to change an existing value.
if type(key) == 'string' then
key = options.translate[key]
end
if options.readOnly then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; the table is read-only',
2
)
elseif options.noOverwrite and args[key] ~= nil then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; overwriting existing arguments is not permitted',
2
)
elseif val == nil then
--[[
-- If the argument is to be overwritten with nil, we need to erase
-- the value in metaArgs, so that __index, __pairs and __ipairs do
-- not use a previous existing value, if present; and we also need
-- to memoize the nil in nilArgs, so that the value isn't looked
-- up in the argument tables if it is accessed again.
--]]
metaArgs[key] = nil
nilArgs[key] = 'h'
else
metaArgs[key] = val
end
end
local function translatenext(invariant)
local k, v = next(invariant.t, invariant.k)
invariant.k = k
if k == nil then
return nil
elseif type(k) ~= 'string' or not options.backtranslate then
return k, v
else
local backtranslate = options.backtranslate[k]
if backtranslate == nil then
-- Skip this one. This is a tail call, so this won't cause stack overflow
return translatenext(invariant)
else
return backtranslate, v
end
end
end
metatable.__pairs = function ()
-- Called when pairs is run on the args table.
if not metatable.donePairs then
mergeArgs(argTables)
metatable.donePairs = true
end
return translatenext, { t = metaArgs }
end
local function inext(t, i)
-- This uses our __index metamethod
local v = t[i + 1]
if v ~= nil then
return i + 1, v
end
end
metatable.__ipairs = function (t)
-- Called when ipairs is run on the args table.
return inext, t, 0
end
return args
end
return arguments
e6be8dfccffa2057c3d50700f350d8d140c1dbf9
Шаблон:Join
10
60
117
2018-06-13T14:41:38Z
wikipedia:ru>Jack who built the house
0
перевод на модуль
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:Separated entries|main|separator={{{separator|}}}}}<noinclude>
{{doc}}
<!-- Категории — на подстраницу /doc, интервики — в Викиданные. -->
</noinclude>
92bb17b5322d3ae0ceab93d4dad3d31810d47eb0
Шаблон:До символа
10
53
103
2018-07-11T11:21:59Z
wikipedia:ru>A particle for world to form
0
Для возможности использовать подстановку.
wikitext
text/x-wiki
{{ {{{|safesubst:}}}#invoke:string2|bs|{{{1|}}}|{{{2|}}}|{{{from|1}}}}}<noinclude>{{doc}}</noinclude>
4cd51dc75d5f365cffac57c9577bd2b2f5c7cc3f
Шаблон:Без начала
10
74
145
2018-07-11T22:30:39Z
wikipedia:ru>A particle for world to form
0
Для возможности использовать подстановку.
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#ifeq:{{<includeonly>safesubst:</includeonly>Str_left|{{{1}}}|{{<includeonly>safesubst:</includeonly>#expr:{{<includeonly>safesubst:</includeonly>str len|{{{2}}}*}}-1}}}}*|{{{2}}}*|{{<includeonly>safesubst:</includeonly>Str_right|{{{1}}}|{{<includeonly>safesubst:</includeonly>#expr:{{<includeonly>safesubst:</includeonly>str len|{{{2}}}*}}-1}}}}|{{{1}}}}}<noinclude>{{doc}}</noinclude>
9fbca6f1fc236cb17fe77d76891e3f9c2afa2117
Шаблон:Str rightc
10
76
149
2018-07-11T22:33:58Z
wikipedia:ru>A particle for world to form
0
Для возможности использовать подстановку.
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>Str sub|{{{1}}}|{{<includeonly>safesubst:</includeonly>#expr:{{<includeonly>safesubst:</includeonly>Str len|{{{1}}}}}-{{{2}}}}}|{{{2}}}}}<noinclude>{{doc}}</noinclude>
0401d500dcc2224d44867ba0ea1f6c0fbeb758a0
Шаблон:Str left
10
42
81
2018-07-11T22:39:12Z
wikipedia:ru>A particle for world to form
0
Для возможности использовать подстановку.
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>padleft:|{{{2|1}}}|{{{1|}}}}}<noinclude>
{{doc}}
</noinclude>
c1f57b63826f4d455dcaec8d2c24a2b8268f42ec
Шаблон:Str sub
10
73
143
2018-09-29T20:45:02Z
wikipedia:ru>TenBaseT
0
категории в документации
wikitext
text/x-wiki
<includeonly>{{{{{|safesubst:}}}#invoke:String|sublength|s={{{1}}}|i={{{2|0}}}|len={{{3|0}}}}}</includeonly><noinclude>
{{doc}}
</noinclude>
3043790f8803e868cf6097b475fd58ba742887fe
Шаблон:Lang-en2
10
63
123
2018-12-28T14:01:00Z
wikipedia:ru>Dima st bk
0
Dima st bk переименовал страницу [[Шаблон:Langi-en2]] в [[Шаблон:Lang-en2]]: под стандарт
wikitext
text/x-wiki
{{langi|en|{{{1}}}}}<noinclude>
{{doc|Lang/doc}}
</noinclude>
0471cf4d45a13ece481915d5c3e55db65d6aca04
Шаблон:No-doc
10
67
131
2019-01-17T08:39:04Z
wikipedia:ru>Dima st bk
0
Защитил страницу [[Шаблон:No-doc]]: критический шаблон или модуль ([Редактирование=только автоподтверждённые] (бессрочно) [Переименование=только администраторы] (бессрочно))
wikitext
text/x-wiki
{{#ifeq: {{SUBPAGENAME}} | doc
|| {{#if: {{#if: {{yesno|{{{nocat|}}}}} | x }}{{#switch: {{NAMESPACE}} | {{ns:10}} | {{ns:828}} = | x }}
|| {{{1|}}}
}}
}}<noinclude>{{doc}}</noinclude>
da013ca5b5f97f94bee392ff3a4488046f2ceac7
Шаблон:Заготовка шаблона
10
102
201
2019-04-25T13:33:44Z
wikipedia:ru>QBA-bot
0
Защитил страницу [[Шаблон:Заготовка шаблона]]: критический шаблон или модуль (каскадная защита) ([Редактирование=только автоподтверждённые] (бессрочно) [Переименование=только автоподтверждённые] (бессрочно))
wikitext
text/x-wiki
{{#invoke:TemplateDataDoc|generateBlank|{{#if:{{{1|}}}|{{{1}}}|{{BASEPAGENAME}}}}|description={{{описание|}}}}}<noinclude>{{doc}}</noinclude>
b451404244fd6898bc134564ddcb8941eca7f64a
Шаблон:Карточка/Викитека
10
50
97
2019-06-16T22:57:42Z
wikipedia:ru>Serhio Magpie
0
Удалять html теги и викификацию, чтобы не ломало форматирование ссылки.
wikitext
text/x-wiki
{{#ifeq:{{{1|}}}|нельзя<!--
-->|© Произведения этого автора [[Свободный контент|несвободны]]<!--
-->|{{#if:{{#invoke:Wikidata/Interproject|getWikisourceLink|p103}}<!--
-->|[[Файл:wikisource-logo.svg|15px|Логотип Викитеки|link={{#invoke:Wikidata/Interproject|getWikisourceLink|p103}}]] [[{{#invoke:Wikidata/Interproject|getWikisourceLink|p103}}|{{#if:{{{2|}}}|{{удалить теги|{{delink|{{{2}}}}}}}|{{Сначала имя|{{PAGENAME}}}}}} в Викитеке]]<!--
-->|{{#if:{{{1|}}}|[[Файл:wikisource-logo.svg|15px|Логотип Викитеки|link=[[:s:{{{1|}}}]]]] [[:s:{{{1|}}}|{{#if:{{{2|}}}|{{удалить теги|{{delink|{{{2}}}}}}}|{{Сначала имя|{{PAGENAME}}}}}} в Викитеке]]}}<!--
-->}}<!--
-->{{#if:{{{nocat|}}}{{NAMESPACE}}||{{#if:{{{1|}}}|[[Категория:Википедия:Ссылка на Викитеку непосредственно в статье]]}}}}<!--
-->}}<noinclude>
{{doc}}
</noinclude>
aac8463be78041fae4a55bf222430b207987f063
Модуль:TableTools
828
10
17
2019-08-26T06:20:31Z
wikipedia:ru>Serhio Magpie
0
Обновлено с https://en.wikipedia.org/w/index.php?title=Module:TableTools&oldid=887403551
Scribunto
text/plain
--[[
------------------------------------------------------------------------------------
-- TableTools --
-- --
-- This module includes a number of functions for dealing with Lua tables. --
-- It is a meta-module, meant to be called from other Lua modules, and should --
-- not be called directly from #invoke. --
------------------------------------------------------------------------------------
--]]
local libraryUtil = require('libraryUtil')
local p = {}
-- Define often-used variables and functions.
local floor = math.floor
local infinity = math.huge
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
--[[
------------------------------------------------------------------------------------
-- isPositiveInteger
--
-- This function returns true if the given value is a positive integer, and false
-- if not. Although it doesn't operate on tables, it is included here as it is
-- useful for determining whether a given table key is in the array part or the
-- hash part of a table.
------------------------------------------------------------------------------------
--]]
function p.isPositiveInteger(v)
if type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity then
return true
else
return false
end
end
--[[
------------------------------------------------------------------------------------
-- isNan
--
-- This function returns true if the given number is a NaN value, and false
-- if not. Although it doesn't operate on tables, it is included here as it is
-- useful for determining whether a value can be a valid table key. Lua will
-- generate an error if a NaN is used as a table key.
------------------------------------------------------------------------------------
--]]
function p.isNan(v)
if type(v) == 'number' and tostring(v) == '-nan' then
return true
else
return false
end
end
--[[
------------------------------------------------------------------------------------
-- shallowClone
--
-- This returns a clone of a table. The value returned is a new table, but all
-- subtables and functions are shared. Metamethods are respected, but the returned
-- table will have no metatable of its own.
------------------------------------------------------------------------------------
--]]
function p.shallowClone(t)
local ret = {}
for k, v in pairs(t) do
ret[k] = v
end
return ret
end
--[[
------------------------------------------------------------------------------------
-- removeDuplicates
--
-- This removes duplicate values from an array. Non-positive-integer keys are
-- ignored. The earliest value is kept, and all subsequent duplicate values are
-- removed, but otherwise the array order is unchanged.
------------------------------------------------------------------------------------
--]]
function p.removeDuplicates(t)
checkType('removeDuplicates', 1, t, 'table')
local isNan = p.isNan
local ret, exists = {}, {}
for i, v in ipairs(t) do
if isNan(v) then
-- NaNs can't be table keys, and they are also unique, so we don't need to check existence.
ret[#ret + 1] = v
else
if not exists[v] then
ret[#ret + 1] = v
exists[v] = true
end
end
end
return ret
end
--[[
------------------------------------------------------------------------------------
-- numKeys
--
-- This takes a table and returns an array containing the numbers of any numerical
-- keys that have non-nil values, sorted in numerical order.
------------------------------------------------------------------------------------
--]]
function p.numKeys(t)
checkType('numKeys', 1, t, 'table')
local isPositiveInteger = p.isPositiveInteger
local nums = {}
for k, v in pairs(t) do
if isPositiveInteger(k) then
nums[#nums + 1] = k
end
end
table.sort(nums)
return nums
end
--[[
------------------------------------------------------------------------------------
-- affixNums
--
-- This takes a table and returns an array containing the numbers of keys with the
-- specified prefix and suffix. For example, for the table
-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will
-- return {1, 3, 6}.
------------------------------------------------------------------------------------
--]]
function p.affixNums(t, prefix, suffix)
checkType('affixNums', 1, t, 'table')
checkType('affixNums', 2, prefix, 'string', true)
checkType('affixNums', 3, suffix, 'string', true)
local function cleanPattern(s)
-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.
s = s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
return s
end
prefix = prefix or ''
suffix = suffix or ''
prefix = cleanPattern(prefix)
suffix = cleanPattern(suffix)
local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'
local nums = {}
for k, v in pairs(t) do
if type(k) == 'string' then
local num = mw.ustring.match(k, pattern)
if num then
nums[#nums + 1] = tonumber(num)
end
end
end
table.sort(nums)
return nums
end
--[[
------------------------------------------------------------------------------------
-- numData
--
-- Given a table with keys like ("foo1", "bar1", "foo2", "baz2"), returns a table
-- of subtables in the format
-- { [1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'} }
-- Keys that don't end with an integer are stored in a subtable named "other".
-- The compress option compresses the table so that it can be iterated over with
-- ipairs.
------------------------------------------------------------------------------------
--]]
function p.numData(t, compress)
checkType('numData', 1, t, 'table')
checkType('numData', 2, compress, 'boolean', true)
local ret = {}
for k, v in pairs(t) do
local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$')
if num then
num = tonumber(num)
local subtable = ret[num] or {}
if prefix == '' then
-- Positional parameters match the blank string; put them at the start of the subtable instead.
prefix = 1
end
subtable[prefix] = v
ret[num] = subtable
else
local subtable = ret.other or {}
subtable[k] = v
ret.other = subtable
end
end
if compress then
local other = ret.other
ret = p.compressSparseArray(ret)
ret.other = other
end
return ret
end
--[[
------------------------------------------------------------------------------------
-- compressSparseArray
--
-- This takes an array with one or more nil values, and removes the nil values
-- while preserving the order, so that the array can be safely traversed with
-- ipairs.
------------------------------------------------------------------------------------
--]]
function p.compressSparseArray(t)
checkType('compressSparseArray', 1, t, 'table')
local ret = {}
local nums = p.numKeys(t)
for _, num in ipairs(nums) do
ret[#ret + 1] = t[num]
end
return ret
end
--[[
------------------------------------------------------------------------------------
-- sparseIpairs
--
-- This is an iterator for sparse arrays. It can be used like ipairs, but can
-- handle nil values.
------------------------------------------------------------------------------------
--]]
function p.sparseIpairs(t)
checkType('sparseIpairs', 1, t, 'table')
local nums = p.numKeys(t)
local i = 0
local lim = #nums
return function ()
i = i + 1
if i <= lim then
local key = nums[i]
return key, t[key]
else
return nil, nil
end
end
end
--[[
------------------------------------------------------------------------------------
-- size
--
-- This returns the size of a key/value pair table. It will also work on arrays,
-- but for arrays it is more efficient to use the # operator.
------------------------------------------------------------------------------------
--]]
function p.size(t)
checkType('size', 1, t, 'table')
local i = 0
for k in pairs(t) do
i = i + 1
end
return i
end
local function defaultKeySort(item1, item2)
-- "number" < "string", so numbers will be sorted before strings.
local type1, type2 = type(item1), type(item2)
if type1 ~= type2 then
return type1 < type2
else -- This will fail with table, boolean, function.
return item1 < item2
end
end
--[[
Returns a list of the keys in a table, sorted using either a default
comparison function or a custom keySort function.
]]
function p.keysToList(t, keySort, checked)
if not checked then
checkType('keysToList', 1, t, 'table')
checkTypeMulti('keysToList', 2, keySort, { 'function', 'boolean', 'nil' })
end
local list = {}
local index = 1
for key, value in pairs(t) do
list[index] = key
index = index + 1
end
if keySort ~= false then
keySort = type(keySort) == 'function' and keySort or defaultKeySort
table.sort(list, keySort)
end
return list
end
--[[
Iterates through a table, with the keys sorted using the keysToList function.
If there are only numerical keys, sparseIpairs is probably more efficient.
]]
function p.sortedPairs(t, keySort)
checkType('sortedPairs', 1, t, 'table')
checkType('sortedPairs', 2, keySort, 'function', true)
local list = p.keysToList(t, keySort, true)
local i = 0
return function()
i = i + 1
local key = list[i]
if key ~= nil then
return key, t[key]
else
return nil, nil
end
end
end
--[[
Returns true if all keys in the table are consecutive integers starting at 1.
--]]
function p.isArray(t)
checkType("isArray", 1, t, "table")
local i = 0
for k, v in pairs(t) do
i = i + 1
if t[i] == nil then
return false
end
end
return true
end
-- { "a", "b", "c" } -> { a = 1, b = 2, c = 3 }
function p.invert(array)
checkType("invert", 1, array, "table")
local map = {}
for i, v in ipairs(array) do
map[v] = i
end
return map
end
--[[
{ "a", "b", "c" } -> { ["a"] = true, ["b"] = true, ["c"] = true }
--]]
function p.listToSet(t)
checkType("listToSet", 1, t, "table")
local set = {}
for _, item in ipairs(t) do
set[item] = true
end
return set
end
--[[
Recursive deep copy function.
Preserves identities of subtables.
]]
local function _deepCopy(orig, includeMetatable, already_seen)
-- Stores copies of tables indexed by the original table.
already_seen = already_seen or {}
local copy = already_seen[orig]
if copy ~= nil then
return copy
end
if type(orig) == 'table' then
copy = {}
for orig_key, orig_value in pairs(orig) do
copy[deepcopy(orig_key, includeMetatable, already_seen)] = deepcopy(orig_value, includeMetatable, already_seen)
end
already_seen[orig] = copy
if includeMetatable then
local mt = getmetatable(orig)
if mt ~= nil then
local mt_copy = deepcopy(mt, includeMetatable, already_seen)
setmetatable(copy, mt_copy)
already_seen[mt] = mt_copy
end
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
function p.deepCopy(orig, noMetatable, already_seen)
checkType("deepCopy", 3, already_seen, "table", true)
return _deepCopy(orig, not noMetatable, already_seen)
end
--[[
Concatenates all values in the table that are indexed by a number, in order.
sparseConcat{ a, nil, c, d } => "acd"
sparseConcat{ nil, b, c, d } => "bcd"
]]
function p.sparseConcat(t, sep, i, j)
local list = {}
local list_i = 0
for _, v in p.sparseIpairs(t) do
list_i = list_i + 1
list[list_i] = v
end
return table.concat(list, sep, i, j)
end
--[[
-- This returns the length of a table, or the first integer key n counting from
-- 1 such that t[n + 1] is nil. It is similar to the operator #, but may return
-- a different value when there are gaps in the array portion of the table.
-- Intended to be used on data loaded with mw.loadData. For other tables, use #.
-- Note: #frame.args in frame object always be set to 0, regardless of
-- the number of unnamed template parameters, so use this function for
-- frame.args.
--]]
function p.length(t)
local i = 1
while t[i] ~= nil do
i = i + 1
end
return i - 1
end
function p.inArray(arr, valueToFind)
checkType("inArray", 1, arr, "table")
-- if valueToFind is nil, error?
for _, v in ipairs(arr) do
if v == valueToFind then
return true
end
end
return false
end
return p
fe918509f168332267834b3a6f5c219a9de5b2e7
Шаблон:Флагификация
10
41
79
2019-09-27T22:34:05Z
wikipedia:ru>Serhio Magpie
0
Отслеживающая категория в случаях, когда в качестве параметра приходит викиссылки или html
wikitext
text/x-wiki
{{#if: {{{1|}}}
| {{#switch: {{str left|{{{1|}}}|1}}
| [ | < | { = [[Категория:Википедия:Страницы с неверным параметром шаблона Флагификация]]
| #default = {{Флагификация/{{{1|}}}
| Флагификация/флагификация
| variant = {{{variant|{{{2|}}}}}}
| размер = {{{размер|}}}
}}
}}
}}<noinclude>{{doc}}</noinclude>
46f4b3bb9842eaf2c75057227b1b76b565563be5
Шаблон:Tl
10
72
141
2019-10-20T16:35:32Z
wikipedia:ru>Helgo13
0
Helgo13 переименовал страницу [[Шаблон:T]] в [[Шаблон:Tl]]
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke: Template call code | withoutParams }}<noinclude>{{doc}}</noinclude>
61fe4d068895a5e7e5802767f5d7df71a7561c57
Шаблон:Карточка/внизу
10
29
55
2019-11-13T23:18:52Z
wikipedia:ru>Serhio Magpie
0
Перенесено в общие стили
wikitext
text/x-wiki
<includeonly>{{#if:{{{внизу|}}}|<tr><td colspan="2" class="infobox-below {{{класс_внизу|}}}" style="{{{стиль_внизу_общий|}}};{{{стиль_внизу|}}}">{{{внизу|}}}</td></tr>}}</includeonly><noinclude>
{{doc}}
</noinclude>
169fb2d10b0847c2fd677eda9f159ba99025198f
Модуль:String2
828
58
113
2020-02-07T22:56:05Z
wikipedia:ru>Serhio Magpie
0
+ ucfirst
Scribunto
text/plain
--[[
Кое-какие дополнительные функции для строк
]]
local M = {
bs=function(f)-- первый параметр до начала второго параметра (или до конца, если он не встретился)
--необяз. 3-й параметр - с какого по номеру (с 1) символа начинать поиск.
return mw.ustring.sub(f.args[1], 1, (mw.ustring.find(f.args[1],f.args[2],tonumber(f.args[3] or 1),true) or 0)-1)
end;
as=function(f)-- первый параметр после начала второго параметра
return mw.ustring.sub(f.args[1], (mw.ustring.find(f.args[1],f.args[2],1,true) or 0)+1)
end;
Tr=function(s,f,t,cf,df,sf)-- транслитерация первого параметра путём замены символов из второго параметра символами из третьего.
-- Отдельными параметрами можно передавать флаги c, d и s, как в Perl; диапазоны в замене не работают, только в левой части
-- (т.е. дефис надо передавать первым или последним). Второй результат - число заменённых символов
local r, l, l2 = {}, mw.ustring.len(f), mw.ustring.len(t);
for i = 1, l do
r[mw.ustring.sub(f,i,i)] = i<=l2 and mw.ustring.sub(t,i,i) or df and '' or mw.ustring.sub(t,l2,l2)
end
local n2=0;
local res, n = mw.ustring.gsub(
s,
('[%s%s]%s'):format(
cf and '^' or '',
f:gsub('%','%%'):gsub(']','%]'):gsub('^%^','%^'),
sf and '+' or ''
),
sf and function(cc)
n2 = n2+mw.ustring.len(cc)-1;
return mw.ustring.gsub(cc,'.',r)
end or r
)
return res, n+n2
end;
-- tr = function(f) return (M.Tr(f.args[1],f.args[2],f.args[3],f.args['c'],f.args['d'],f.args['s'])) end;-- транслитерировать
-- trс = function(f) return ({M.Tr(f.args[1],f.args[2],f.args[3],f.args['c'],f.args['d'],f.args['s'])})[2] end;-- посчитать символы
Trg = function(s,t,f,fi)-- Производит замену строк произвольной длины (если с fi, регистр не учитывает).
-- Приоритет - по порядку в таблицах.
for n,p in ipairs(t) do
t[n] = {fi and mw.ustring.upper(p) or p,mw.ustring.len(p)}
end
local r,i,l,N = {},1,mw.ustring.len(s),0
while i<=l do
(function()
for n,p in ipairs(t) do
if ( fi and mw.ustring.upper(mw.ustring.sub(s,i,i+p[2]-1)) or mw.ustring.sub(s,i,i+p[2]-1) ) == p[1] then
table.insert(r,f[n]);
i = i+p[2]; N=N+1;
return
end
end
table.insert(r,mw.ustring.sub(s,i,i));
i=i+1;
return
end)()
end
return table.concat(r),N
end;
trg = function(frame)--Работает с номерными аргументами шаблона,если задан параметр u, иначе со своими.
-- Заменяет в первом аргументе аргументы 2, 4, 6... на аргументы 3, 5, 7...
local tf, t, f, i= frame.args['u'] and frame.getParent() or f, {}, {}, 1;
while tf.args[2*i] do t[tf.args[2*i]]=tf.args[2*i+1] or '' end
return ( M.Trg(tf.args[1],t,f,(frame.args['i'] or '')~='') )
end;
join = function (f) --объединяет нумерованные аргументы вызвавшего шаблона
-- от from или 1 до to или первого отсутствующего
-- через первый параметр invoke. Последний элемент можно присоединять иначе, задав второй параметр.
-- По умолчанию ',' & 'и'
-- Если 3-й параметр invoke — "s", строки из пробелов игнорируются; если "_", игнорируются пустые строки
local t, tf, i = {}, f:getParent(), tonumber(f.args.from) or 1
local k,j,m = tonumber(f.args.to),i,f.args[3]
while k and i<=k or tf.args[i] do
if (
({
['_']=function(s)return s~=''end;
['s']=function(s)return not tostring(s):match("^%s*$")end
})[m] or function() return true end
)(tf.args[i]) then
t[j]=tf.args[i];
j=j+1
end;
i=i+1
end
return mw.text.listToText(t,f.args[1],f.args[2] or f.args[1])
end
}
function M.formatRound(frame) --форматирует число, чтобы оно имело order знаков после запятой
return string.format("%0."..frame.args[2].."f",tonumber(frame.args[1]));
end
-- если строка s содержит число, увеличивает первое такое число на n, иначе возращает пустую строку.
-- если число начинается на 0, то увеличенное число будет содержать по крайне мере столько цифр сколько исходное.
function M.increase(s, n)
local a,b,c = string.match(s, "([^0-9]*)([0-9]+)(.*)")
if b==nil then return s end
local num = tonumber(b) + n
if b:sub(1,1)=='0'
then b = string.format("%0"..b:len().."d", num)
else b=num
end
return a .. b .. c
end
function M.ucfirst(frame )
local s = mw.text.trim( frame.args[1] or "" )
local s1 = ""
-- if it's a list chop off and (store as s1) everything up to the first <li>
local lipos = string.find(s, "<li>" )
if lipos then
s1 = string.sub(s, 1, lipos + 3)
s = string.sub(s, lipos + 4)
end
-- s1 is either "" or the first part of the list markup, so we can continue
-- and prepend s1 to the returned string
local letterpos
if string.find(s, "^%[%[[^|]+|[^%]]+%]%]") then
-- this is a piped wikilink, so we capitalise the text, not the pipe
local _
_, letterpos = string.find(s, "|%A*%a") -- find the first letter after the pipe
else
letterpos = string.find(s, '%a')
end
if letterpos then
local first = string.sub(s, 1, letterpos - 1)
local letter = string.sub(s, letterpos, letterpos)
local rest = string.sub(s, letterpos + 1)
return s1 .. first .. string.upper(letter) .. rest
else
return s1 .. s
end
end
return M
1d51eb45a573b689485dad672c0968c18ec3b342
Модуль:Separated entries
828
69
135
2020-07-05T06:33:20Z
wikipedia:ru>Serhio Magpie
0
+ newline
Scribunto
text/plain
-- This module takes positional parameters as input and concatenates them with
-- an optional separator. The final separator (the "conjunction") can be
-- specified independently, enabling natural-language lists like
-- "foo, bar, baz and qux".
local compressSparseArray = require('Module:TableTools').compressSparseArray
local p = {}
function p._main(args)
local separator = args.separator
-- Decode (convert to Unicode) HTML escape sequences, such as " " for space.
and mw.text.decode(args.separator) or ''
local conjunction = args.conjunction and mw.text.decode(args.conjunction) or separator
-- Discard named parameters.
local values = compressSparseArray(args)
return mw.text.listToText(values, separator, conjunction)
end
local function makeInvokeFunction(separator, conjunction)
return function (frame)
local args = require('Module:Arguments').getArgs(frame)
args.separator = separator or args.separator
args.conjunction = conjunction or args.conjunction
return p._main(args)
end
end
p.main = makeInvokeFunction()
p.br = makeInvokeFunction('<br />')
p.newline = makeInvokeFunction('\n')
p.comma = makeInvokeFunction(mw.message.new('comma-separator'):plain())
return p
33a68f0a46d62c42b6523a548f0f881e82ecfe58
Модуль:Transclude
828
36
69
2020-11-17T12:38:34Z
wikipedia:ru>Wikisaurus
0
пропускать пустые параметры в forall и join
Scribunto
text/plain
local p={}
-- Вызывает внутренний шаблон с аргументами объемлющего шаблона
function p.call(frame)
local template = frame.args[1]
local args = frame:getParent().args
return frame:expandTemplate{ title=template, args=args }
end
-- Общая реализация для forall и call
local function forallImpl(args, separator, conjunction, func)
-- нумерованные ключи из args
local keys = {}
-- перебор в произвольном порядке, даже для нумерованных ключей
for key, value in pairs(args) do
if type(key) == 'number' and value and value ~= '' then
table.insert(keys, key)
end
end
table.sort(keys)
local results = {}
for _, key in ipairs(keys) do
local value = func(args[key])
table.insert(results, value)
end
return mw.text.listToText(results, separator, conjunction)
end
-- Вызывает внутренний шаблон, передавая ему нумерованные параметры объемлющего шаблона по-одному
function p.forall(frame)
local template = frame.args[1]
local separator = frame.args.separator or ''
local conjunction = frame.args.conjunction or separator
local args = frame:getParent().args
local func = function(value)
return frame:expandTemplate{ title = template, args = {value} } -- или другой frame?
end
return forallImpl(args, separator, conjunction, func)
end
-- Берёт нумерованные аргументы объемлющего шаблона и склеивает их в единую строку
function p.join(frame)
local separator = frame.args[1] or ''
local conjunction = frame.args[2] or separator
local args = frame:getParent().args
local func = function(value)
return value
end
return forallImpl(args, separator, conjunction, func)
end
-- Служебная функция: удаляет дубликаты из отсортированного массива с нумерованными индексами
local function deleteDuplicates(args)
local res = {}
for key, value in pairs(args) do
if args[key+1] ~= value then
table.insert(res, value)
end
end
return res
end
-- Вызывает внутренний шаблон несколько раз, передавая в него блоки аргументов объемлющего шаблона
function p.npc(frame)
local args = frame:getParent().args
local templateFrame = frame:getParent()
local template = frame.args[1]
-- определение, блоки аргументов с какими номерами нужны:
-- если в объемлющем шаблоне есть "параметр12" и в вызове модуля есть "параметр", то вызывается 12-й блок
local nums = {}
for key, _ in pairs(args) do
local main, num = string.match(key, '^(.-)%s*(%d*)$')
num = tonumber(num)
-- учитывать "параметр12", только если задано "параметр"
if num and frame.args[main] then
table.insert(nums, num)
end
end
table.sort(nums)
nums = deleteDuplicates(nums)
-- проходить по нужным номерам блоков по возрастанию и однократно
-- подставлять в шаблон:
-- 1. общие аргументы данного модуля
-- 2. аргументы объемлющего шаблона вида "параметр12" как "параметр" в 12-й блок
local results = {}
for _, blockNum in ipairs(nums) do
-- общие аргументы модуля, которые передаются в каждый блок
local blockArgs = mw.clone(frame.args)
-- metatable ломает expandTemplate
setmetatable(blockArgs, nil)
for key, value in pairs(args) do
local main, num = string.match(key, '^(.-)%s*(%d*)$')
num = tonumber(num)
-- передавать "параметр12" как "параметр" в 12-й блок, только если есть "параметр" в вызове модуля
if blockNum == num and frame.args[main] then
blockArgs[main] = value
end
end
local blockText = templateFrame:expandTemplate{ title=template; args=blockArgs }
table.insert(results, blockText)
end
return table.concat(results)
end
-- Действует аналогично forall по числовой переменной, изменяющейся (по умолчанию, от 1) до f.args[2].
function p.cycle(f)
local tf,ac,op=f:getParent(), {}, f.args.output or 'inline';
local sep='';
if op == 'newline' then
sep='\n';
end
for p,k in pairs(f.args) do
if type(p)=='number' then
if p>2 then ac[p-1]=k end
else ac[p]=k
end
end
local s,fh = f.args[2]:match('^%s*(%-?%d+)%s*%.%.') or 1,
f.args[2]:match('%.%.%s*(%S.*)%s*$') or f.args[2] or '';
fh=tonumber(fh) or fh:match('^%s*(.-)%s*$');
s=tonumber(s);
local acr={};
if not s then error('Начало цикла «'..s..'» — не число') end
local function dc(order)
local r=tf:expandTemplate{ title=f.args[1]; args={s,unpack(ac)} }
if order == 'desc' then
s=s-1;
else
s=s+1;
end
if r~='' then table.insert(acr,r); return r end
end
if type(fh)=='number' then
if fh > s then
while s<=fh do dc('asc') end
else
while s>=fh do dc('desc') end
end
elseif fh~='' then
while tf:expandTemplate{ title=fh; args={s,unpack(ac)} } do dc('asc') end
else
while dc('asc') do end
end
return table.concat(acr, sep)
end
return p
c17cfab4cebc23157f5ab8d18c7e4f5c273bfa59
Модуль:Hash
828
79
155
2021-02-07T10:01:11Z
wikipedia:ru>Grain of sand
0
+ list() для вывода списка доступных алгоритмов
Scribunto
text/plain
local getArgs = require('Module:Arguments').getArgs
local p = {}
local function inTable(table, value)
for k, v in pairs(table) do
if v == value then
return true
end
end
return false
end
function p.list(frame)
return table.concat(mw.hash.listAlgorithms(), '; ')
end
function p.main(frame)
local args = getArgs(frame, { frameOnly = true })
local algorithm
if not args[1] then
return '<span class="error">Не указана строка для хеширования.</span>'
end
if args[2] then
if not inTable(mw.hash.listAlgorithms(), args[2]) then
return '<span class="error">Алгоритм хеширования ' .. args[2] .. ' не поддерживается, или вы неточно указали его имя. Используйте функцию <kbd>mw.hash.listAlgorithms()</kbd> для получения списка доступных алгоритмов.</span>'
end
algorithm = args[2]
else
-- Алгоритм выбран из соображений быстродействия (см. [[:en:Fowler–Noll–Vo hash function]]),
-- 64-битная функция используется для уменьшения вероятности коллизий до пренебрежимо малой
-- величины. Возможно, есть лучшая опция — проверяйте.
algorithm = 'fnv164'
end
return mw.hash.hashValue(algorithm, args[1])
end
return p
5d18513e574435f191164695449a620b031f93ec
Модуль:Infocards/dateCat
828
56
109
2021-02-14T08:16:01Z
wikipedia:ru>WindEwriX
0
Защитил страницу [[Модуль:Infocards/dateCat]]: критический шаблон или модуль: включён в [[Модуль:Wikidata/date]] и [[Модуль:Infocards]] ([Редактирование=администраторы и инженеры] (бессрочно) [Переименование=администраторы и инженеры] (бессрочно))
Scribunto
text/plain
local p = {}
p.categoryUnknownBirthDate = '[[Категория:Персоналии, чья дата рождения не установлена]]'
p.categoryUnknownDeathDate = '[[Категория:Персоналии, чья дата смерти не установлена]]'
p.categoryBigCurrentAge = '[[Категория:Персоналии с большим текущим возрастом]]' --бывш. [[Категория:Википедия:Статьи о персоналиях с большим текущим возрастом]]
p.categoryNegativeAge = '[[Категория:Персоналии с отрицательным возрастом]]'
-- p.categoryBigDeathAge = '[[Категория:Википедия:Статьи о персоналиях с большим возрастом во время смерти]]' //deleted -d.bratchuk 05-07-2016
p.categoryBiographiesOfLivingPersons = '[[Категория:Википедия:Биографии современников]]'
p.categoryRecentlyDeceased = '[[Категория:Персоналии, умершие менее года назад]]'
p.categoryManualWikification = '[[Категория:Википедия:Статьи с ручной викификацией дат в карточке]]'
p.categoryNoBirthDate = '[[Категория:Персоналии без указанной даты рождения]]' --бывш. [[Категория:Википедия:Персоны без указанной даты рождения]]
return p
6b27e44bc0a4aaafa42074ca16db92b13e4999d4
Шаблон:Doc/end
10
87
171
2021-02-14T18:18:13Z
wikipedia:ru>Putnik
0
для модулей предзагрузка нормально не работает
wikitext
text/x-wiki
<includeonly></div>
</div><templatestyles src="Шаблон:Doc/styles.css" />{{#ifexpr: {{NAMESPACENUMBER}} mod 2 = 1 <!-- Например, [[Обсуждение MediaWiki:Robots.txt]] -->
| {{^|1em}}
| <div class="ts-doc-footer plainlinks">
{{#ifeq: {{str left|{{PAGENAME}}|9}}
| Песочница
|
| {{#ifeq: {{str rightc|{{PAGENAME}}|10}}
| /песочница
|
| Во избежание поломок страниц, использующих этот {{#ifeq: {{NAMESPACE}}
| Модуль
| модуль
| шаблон
}}, экспериментируйте в [[Википедия:Правка и тестирование шаблонов в песочнице|песочнице]] <small style="font-style:normal;">({{#ifexist: {{FULLPAGENAME}}/песочница
| [{{fullurl:{{FULLPAGENAME}}/песочница|action=edit}} редактировать] {{!}} [{{fullurl:Special:ComparePages|page1={{FULLPAGENAMEE}}&page2={{FULLPAGENAMEE}}/песочница}} разница] {{#ifexist: {{FULLPAGENAME}}/тесты | {{!}} [[{{FULLPAGENAME}}/тесты|тесты]] }}
| {{#ifeq: {{NAMESPACE}} | Модуль | [{{fullurl:{{FULLPAGENAME}}/песочница|action=edit}} создать] | [{{fullurl:{{FULLPAGENAME}}/песочница|action=edit&preload=Шаблон:Doc/предзагрузка-песочница}} создать] {{!}} [{{fullurl:{{FULLPAGENAME}}/песочница|action=edit&preload=Шаблон:Doc/зеркало}} зеркало] }}
}})</small> или {{#ifeq: {{NAMESPACE}}
| Модуль
| [[Модуль:Песочница|песочнице для модулей]]
| своём [[ВП:ЛП|личном пространстве]]
}}.<br>
}}
}}{{#ifexist: {{FULLPAGENAME}}/doc | Пожалуйста, добавляйте категории на подстраницу [[/doc]]. }}[[Special:PrefixIndex/{{FULLPAGENAME}}/|Подстраницы этого {{#ifeq: {{NAMESPACE}}
| Модуль
| модуля
| шаблона
}}]].
</div>
}}</includeonly><noinclude>{{doc}}</noinclude>
758a01a3d76e14ef14b2b0ee047ac47ddac8fd8e
Шаблон:Пример с именами параметров
10
107
211
2021-02-28T18:08:15Z
wikipedia:ru>Grain of sand
0
Grain of sand переименовал страницу [[Шаблон:Parameter names example]] в [[Шаблон:Пример с именами параметров]]: русификация
wikitext
text/x-wiki
<includeonly>{{#invoke:Parameter names example|main}}</includeonly><noinclude>
{{Doc}}
</noinclude>
2118cbf70aef4a440190a91ba85327a5cb8d3808
Шаблон:Parameter names example
10
109
215
2021-02-28T18:08:16Z
wikipedia:ru>Grain of sand
0
Grain of sand переименовал страницу [[Шаблон:Parameter names example]] в [[Шаблон:Пример с именами параметров]]: русификация
wikitext
text/x-wiki
#перенаправление [[Шаблон:Пример с именами параметров]]
f42e4b1940da05c9e876c1c77cffa5c78e59c68d
Модуль:Color contrast
828
64
125
2021-03-01T22:40:23Z
wikipedia:ru>Grain of sand
0
local
Scribunto
text/plain
--
-- This module implements
-- {{Color contrast ratio}}
-- {{Greater color contrast ratio}}
-- {{ColorToLum}}
-- {{RGBColorToLum}}
--
local p = {}
local HTMLcolor = mw.loadData( 'Module:Color contrast/colors' )
local function sRGB ( v )
if (v <= 0.03928) then
v = v / 12.92
else
v = math.pow((v+0.055)/1.055, 2.4)
end
return v
end
local function rgbdec2lum( R, G, B )
if ( 0 <= R and R < 256 and 0 <= G and G < 256 and 0 <= B and B < 256 ) then
return 0.2126 * sRGB(R/255) + 0.7152 * sRGB(G/255) + 0.0722 * sRGB(B/255)
else
return ''
end
end
local function hsl2lum( h, s, l )
if ( 0 <= h and h < 360 and 0 <= s and s <= 1 and 0 <= l and l <= 1 ) then
local c = (1 - math.abs(2*l - 1))*s
local x = c*(1 - math.abs( math.fmod(h/60, 2) - 1) )
local m = l - c/2
local r, g, b = m, m, m
if( 0 <= h and h < 60 ) then
r = r + c
g = g + x
elseif( 60 <= h and h < 120 ) then
r = r + x
g = g + c
elseif( 120 <= h and h < 180 ) then
g = g + c
b = b + x
elseif( 180 <= h and h < 240 ) then
g = g + x
b = b + c
elseif( 240 <= h and h < 300 ) then
r = r + x
b = b + c
elseif( 300 <= h and h < 360 ) then
r = r + c
b = b + x
end
return rgbdec2lum(255*r, 255*g, 255*b)
else
return ''
end
end
local function color2lum( c )
if (c == nil) then
return ''
end
-- whitespace
c = c:match( '^%s*(.-)[%s;]*$' )
-- lowercase
c = c:lower()
-- first try to look it up
local L = HTMLcolor[c]
if (L ~= nil) then
return L
end
-- convert from hsl
if mw.ustring.match(c,'^hsl%([%s]*[0-9][0-9%.]*[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local h, s, l = mw.ustring.match(c,'^hsl%([%s]*([0-9][0-9%.]*)[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return hsl2lum(tonumber(h), tonumber(s)/100, tonumber(l)/100)
end
-- convert from rgb
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*%)$')
return rgbdec2lum(tonumber(R), tonumber(G), tonumber(B))
end
-- convert from rgb percent
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return rgbdec2lum(255*tonumber(R)/100, 255*tonumber(G)/100, 255*tonumber(B)/100)
end
-- remove leading # (if there is one) and whitespace
c = mw.ustring.match(c, '^[%s#]*([a-f0-9]*)[%s]*$')
-- split into rgb
local cs = mw.text.split(c or '', '')
if( #cs == 6 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[2])
local G = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[4])
local B = 16*tonumber('0x' .. cs[5]) + tonumber('0x' .. cs[6])
return rgbdec2lum(R, G, B)
elseif ( #cs == 3 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[1])
local G = 16*tonumber('0x' .. cs[2]) + tonumber('0x' .. cs[2])
local B = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[3])
return rgbdec2lum(R, G, B)
end
-- failure, return blank
return ''
end
function p._greatercontrast(args)
local bias = tonumber(args['bias'] or '0') or 0
local v1 = color2lum(args[1] or '')
local c2 = args[2] or '#FFFFFF'
local v2 = color2lum(c2)
local c3 = args[3] or '#000000'
local v3 = color2lum(c3)
local ratio1 = 0;
local ratio2 = 0;
if (type(v1) == 'number' and type(v2) == 'number') then
ratio1 = (v2 + 0.05)/(v1 + 0.05)
ratio1 = (ratio1 < 1) and 1/ratio1 or ratio1
end
if (type(v1) == 'number' and type(v3) == 'number') then
ratio2 = (v3 + 0.05)/(v1 + 0.05)
ratio2 = (ratio2 < 1) and 1/ratio2 or ratio2
end
return (ratio1 + bias > ratio2) and c2 or c3
end
function p._ratio(args)
local v1 = color2lum(mw.text.unstripNoWiki(args[1] or ''))
local v2 = color2lum(mw.text.unstripNoWiki(args[2] or ''))
if (type(v1) == 'number' and type(v2) == 'number') then
-- v1 should be the brighter of the two.
if v2 > v1 then
v1, v2 = v2, v1
end
return (v1 + 0.05)/(v2 + 0.05)
else
return args['error'] or '?'
end
end
function p._styleratio(args)
local style = (args[1] or ''):lower()
local bg, fg = 'white', '#202122'
local lum_bg, lum_fg = 1, 0.016
if args[2] then
local lum = color2lum(args[2])
if lum ~= '' then bg, lum_bg = args[2], lum end
end
if args[3] then
local lum = color2lum(args[3])
if lum ~= '' then fg, lum_fg = args[3], lum end
end
local slist = mw.text.split(style or '', ';')
for k = 1, #slist do
local s = slist[k]
local k, v = s:match( '^[%s]*([^:]-):([^:]-)[%s;]*$' )
k = k or ''
v = v or ''
if (k:match('^[%s]*(background)[%s]*$') or k:match('^[%s]*(background%-color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_bg = v, lum end
elseif (k:match('^[%s]*(color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_fg = v, lum end
end
end
if lum_bg > lum_fg then
return (lum_bg + 0.05)/(lum_fg + 0.05)
else
return (lum_fg + 0.05)/(lum_bg + 0.05)
end
end
function p.lum(frame)
return color2lum(frame.args[1] or frame:getParent().args[1])
end
function p.ratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._ratio(args)
end
function p.styleratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._styleratio(args)
end
function p.greatercontrast(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._greatercontrast(args)
end
return p
cce580326bee8eaf3c81df6c76c04a9a2909dfa2
Модуль:Parameter names example
828
108
213
2021-03-03T19:37:12Z
wikipedia:ru>Grain of sand
0
шаблон переименован
Scribunto
text/plain
-- This module implements {{parameter names example}}.
local p = {}
local function makeParam(s)
local lb = '{'
local rb = '}'
return lb:rep(3) .. s .. rb:rep(3)
end
local function italicize(s)
return "''" .. s .. "''"
end
local function plain(s)
return s
end
function p._main(args, frame)
-- Find how we want to format the arguments to the template.
local formatFunc
if args._display == 'italics' or args._display == 'italic' then
formatFunc = italicize
elseif args._display == 'plain' then
formatFunc = plain
else
formatFunc = makeParam
end
-- Build the table of template arguments.
local targs = {}
for k, v in pairs(args) do
if type(k) == 'number' then
targs[v] = formatFunc(v)
elseif not k:find('^_') then
targs[k] = v
end
end
-- Find the template name.
local template
if args._template then
template = args._template
else
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.prefixedText:find('/sandbox$') or currentTitle.prefixedText:find('/песочница$') then
template = currentTitle.prefixedText
else
template = currentTitle.basePageTitle.prefixedText
end
end
-- Call the template with the arguments.
frame = frame or mw.getCurrentFrame()
local success, result = pcall(
frame.expandTemplate,
frame,
{title = template, args = targs}
)
if success then
return result
else
return ''
end
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Шаблон:Пример с именами параметров'
})
return p._main(args, frame)
end
return p
64667ee447347f717db659027d7c4ec864230a93
Шаблон:Wikidata
10
26
49
2021-04-01T12:24:50Z
wikipedia:ru>MBH
0
[[ВП:Откат|откат]] правок [[Special:Contribs/Lê Lợi (bot)|Lê Lợi (bot)]] ([[UT:Lê Lợi (bot)|обс.]]) к версии Wikisaurus
wikitext
text/x-wiki
<includeonly>{{#invoke:Wikidata|formatProperty|property={{{1|}}}|value={{{2|}}}}}</includeonly><noinclude>{{doc}}</noinclude>
9d3d422eca39504b018df6ec0bb047392a7aba7e
Модуль:Infobox
828
35
67
2021-08-16T20:12:46Z
wikipedia:ru>Putnik
0
scope="colgroup" для заголовков
Scribunto
text/plain
local p = {};
local yesno = require('Module:Yesno')
local function _renderLine( frame, args, i )
if args[ 'заголовок' .. i ] and args[ 'заголовок' .. i ] == '-' then
return ''
elseif args[ 'заголовок' .. i ] and args[ 'заголовок' .. i ] ~= '' then
local style = ( args[ 'стиль_заголовков' ] or '' ) .. ( args[ 'стиль_заголовка' .. i ] or '' );
local class = ( args[ 'класс' .. i ] or '' );
return '\n<tr>\n<th colspan="2" scope="colgroup" class="infobox-header ' .. class .. '" style="' .. style .. '">' ..
args[ 'заголовок' .. i ] ..
'</th>\n</tr>';
end
if args[ 'блок' .. i ] and args[ 'блок' .. i ] ~= '' then
return args[ 'блок' .. i ];
end
local text = args[ 'текст' .. i ] or '';
if args[ 'викиданные' .. i ] and args[ 'викиданные' .. i ] ~= '' then
text = frame:expandTemplate{ title = 'Wikidata', args = {
args[ 'викиданные' .. i ],
text,
from = args[ 'from' ] or ''
} };
end
if text ~= '' then
local label = args[ 'метка' .. i ] or '';
local class = args[ 'класс' .. i ] or '';
if string.find(class, 'noplainlist') == nil and string.find(class, 'nofirstlevel') == nil then
class = class .. ' plainlist';
end
if class ~= '' then
class = ' class="' .. class .. '"';
end
local style = ( args[ 'стиль_текстов' ] or '' ) .. ( args[ 'стиль_текста' ] or '' ) .. ( args[ 'стиль_текста' .. i ] or '' );
if label == '' then
style = 'text-align:center;' .. style;
end
if style ~= '' then
style = ' style="' .. style .. '"';
end
if label ~= '' then
local labelClass = args[ 'класс_меток' ] or '';
if string.find(labelClass, 'noplainlist') == nil and string.find(labelClass, 'nofirstlevel') == nil then
labelClass = labelClass .. ' plainlist';
end
if labelClass ~= '' then
labelClass = ' class="' .. labelClass .. '"';
end
local labelStyle = ( args[ 'стиль_меток' ] or '' ) .. ( args[ 'стиль_метки' .. i ] or '' );
if labelStyle ~= '' then
labelStyle = ' style="' .. labelStyle .. '"';
end
return '\n<tr>\n<th scope="row"' .. labelClass .. labelStyle .. '>' .. label .. '</th>' ..
'\n<td' .. class .. style .. '>\n' .. text .. '</td>\n</tr>';
end
return '\n<tr>\n<td colspan="2"' .. class .. style .. '>\n' .. text .. '</td>\n</tr>';
end
return '';
end
local function maxNumber ( args )
local maxNumber = 0
for argName, _ in pairs(args) do
local argNumber = mw.ustring.match(argName, '^[^0-9]+([0-9]+)$')
if argNumber and tonumber(argNumber) > maxNumber then
maxNumber = tonumber(argNumber)
end
end
return maxNumber
end
function p.renderLine( frame )
local args = frame:getParent().args;
return _renderLine(frame, args, '')
end
function p.renderLines( frame )
local args = frame:getParent().args;
local res = ''
local header, text = '', ''
local autoHeaders = yesno(args [ 'автозаголовки' ] or 'false', false)
for i = 1, maxNumber(args) do
if args[ 'заголовок' .. i ] and args[ 'заголовок' .. i ] ~= '' then
if text ~= '' or not autoHeaders then
res = res .. header .. text
end
header, text = _renderLine(frame, args, i), ''
else
text = text .. _renderLine(frame, args, i)
end
end
if text ~= '' or not autoHeaders then
res = res .. header .. text
end
return res
end
return p;
c830c997bd3d15923f347277e3b0ae71b7ba917e
Модуль:Dates
828
61
119
2021-10-11T18:35:23Z
wikipedia:ru>Wikisaurus
0
параметр nolinks для отключения викификации даты в [[Модуль:Wikidata/date]]
Scribunto
text/plain
--[[
В это модуле собраны функции, связанные с работой с датами.
]]
local monthg = {'января', 'февраля', 'марта', 'апреля', 'мая', 'июня',
'июля', 'августа', "сентября", "октября", "ноября", "декабря"}
local monthd = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
local function DecodeDate(d)-- Ч, М, Г, СЧ, СМ, СГ, хвост
--дата: "%-?%d+"=год, "%d+%.%d+"=число месяца, "%d+%.%d+%.%-?%d+"=ЧМГ,
-- потом в скобках м.б. переопределено для старого стиля начиная с числа
local nd=d:match("^[%d.-]*");
local od=d:match("^[%d.-]*%s*%(%s*([%d.-]*)%s*%)");
local tail = d:match("^[%d.-]+%s*%(%s*[%d.-]+%s*%)%s*(%S.*)") or d:match("^[%d.-]+%s*([^%s%d].*)");
if nd:match('^%-?%d+$' ) then
return nil, nil, tonumber(nd), nil, nil, od and tonumber(od:match("%-?%d+$")),tail
else
local j,m,y=nd:match("^(%d+)%.(%d+)%.?(%-?%d*)");
if j then
if od then
local oj, om, oy = od:match("^(%d+)%.?(%d*)%.?(%-?%d*)");
return j and tonumber(j),
m and tonumber(m),
y>'' and tonumber(y) or nil,
oj and tonumber(oj),
om>'' and tonumber(om) or nil,
oy>'' and tonumber(oy) or nil,
tail
end
return j and tonumber(j), m and tonumber(m), y>'' and tonumber(y) or nil, nil, nil, nil, tail
else return nil
end
end
end
local function Diffy(d1,m1,y1,d0,m0,y0)--аналог Персона/Дата/Прошло лет
return y1-y0 - ( y1*y0<=0 and 1 or 0 ) - ( (m1<m0 or m1==m0 and d1<d0) and 1 or 0 )
end
local function Year0(y,t)-- аналог Год0
if y>0 then return table.concat{
'[[', tostring(y), ' год|', t and tostring(y)..' '..t or tostring(y), ']]'
} else return table.concat{
'[[', tostring(-y), ' год до н. э.|',
t and tostring(-y)..' '..t or tostring(-y),
' до н. э.]]'
}
end
end
local function FormDate(j,m,y,oj,om,oy,mo)-- ~ Персона/Дата/Logic 4
if j then
if not m then return "''формат неверен''" end
if y then return
string.format(
'<span class="nowrap">%s<span style="display:none">(<span class="%s">%04i-%02i-%02i</span>)</span></span>',
table.concat(
oj and (
om and (
oy and {-- ДД ММММ ГГГГ ([[ДД ММММ]] [[ГГГГ]])
oj,' ',monthg[om],' ',oy,
'</span> <span class="nowrap">([[',
j, ' ', monthg[m],']] ',Year0(y),')'
} or {-- ДД ММММ ([[ДД ММММ]]) [[ГГГГ]]
oj,' ',monthg[om],' ([[',j,' ',monthg[m],']]) ',Year0(y)
}
) or {-- ДД [[ДД ММММ|(ДД) ММММ]] [[ГГГГ]]
oj,' [[',j,' ',monthg[m],'|','(',j,') ',monthg[m],']] ',Year0(y)
}
) or {'[[',j,' ',monthg[m],']] ',Year0(y)}
),--/table.concat
({['Рождения']='bday',['Смерти']='dday'})[mo] or '',
y,m,j
)--/string.format
else return
'<span class="nowrap">' .. table.concat(
oj and (
om and {-- ДД ММММ ([[ДД ММММ]])
oj,' ',monthg[om],' ([[',j,' ',monthg[m],']])</span>'
} or {-- ДД [[ДД ММММ|(ДД) ММММ]]
oj,' [[',j,' ',monthg[m],'|','(',j,') ',monthg[m],']]</span>'
}
) or {'[[',j,' ',monthg[m],']]</span>'}
)
end
else
return y and string.format(
'<span class="nowrap">%s<span style="display:none;">(<span class="bday">%04i</span>)</span></span>',
Year0(y,'год'),y) or "''формат неверен''"
end
end
local function GetDate(D)--dd.mm.-?yyyy или -?yyyy-mm-dd в три переменных d,m,y
local d,m,y = d:match('^%s*(%d%d?)[/.]([01]?%d)[/.](%-?%d+)')
if not d then y,m,d = D:match('^%s*(%-?%d+)[-\\]0*(1?%d)[-\\]0*(%d+)') end
return tonumber(d),tonumber(m),tonumber(y)
end
local function Cmp(a,b)--Сравнивает две даты, результат соответственно -1, 0 или 1
local d1,m1,y1 = GetDate(a)
local d2,m2,y2 = GetDate(b)
return d1 and d2 and (--nil, если формат не опознан
y1==y2 and (
m1==m2 and (
d1==d2 and 0 or d1<d2 and -1 or 1
) or m1<m2 and -1 or 1
) or y1<y2 and -1 or 1
)
end
local function Yyyymmdd(r)--Переводит русскую дату в YYYY,MM,DD
local d, m, y, M = mw.ustring.match(r, "^%s*(%d%d?)%s+([а-яА-Я]+)%s+(%d+)")
if not m then return nil end
m = mw.ustring.lower(m)
--тупо перебор
for i = 1, 12 do
if m == monthg[i] then
M = i
break
end
end
if not M then
return nil
end
return tonumber(y), M, tonumber(d)
end
local p = {}
p = {
ifdate=function(f)-- Для шаблона "Если дата", имитирует старое поведение
-- Аргументы передаются шаблону
return f:getParent().args[ mw.ustring.match(frame.args[1],"^[ %d.%-−%()]*$") and 2 or 3 ]
end;
DecodeDate = DecodeDate;
Diffy = Diffy;
Year0 = Year0;
GetDate = GetDate;
Cmp = Cmp;
Yyyymmdd = Yyyymmdd;
diffy = function(f)-- принимает параметры #invoke в виде двух строк-дат
local d1,m1,y1=DecodeDate(f.args[1]);
local d0,m0,y0=DecodeDate(f.args[2])
return Diffy(d1,m1,y1,d0,m0,y0)
end;
monthg=function(f) return monthg[ f.args[1] or f:getParent().args[1] ] end;--realmonth
persdate=function(f)-- Для шаблона Персона/Дата;{{#invoke:dates|persdate|nocat={{NAMESPACE}}}}
local frame=f:getParent();
local catpref,mo,d,d2={['Рождения']='Родившиеся',['Смерти']='Умершие'}, frame.args[1],frame.args[2],frame.args[3]
local cat, j,m,y,oj,om,oy,tail, j2,m2,y2, age = ''
if d then
j,m,y,oj,om,oy,tail=DecodeDate(d:gsub('−','-'));
if not (j or y) then
return (frame.args.nocat and d or d..'[[Category:Википедия:Статьи с ручной викификацией дат в карточке]]')
end
end;
if d2 then
j2,m2,y2 = DecodeDate(d2:gsub('−','-'));
end;
return table.concat{
FormDate(j,m,y,oj,om,oy,mo),
( (frame.args['nopersoncat'] or '')~='' or (f.args['nocat'] or '')~='' ) and '' or table.concat{
'[[Category:Персоналии по алфавиту]]',
j and string.format('[[Category:%s %i %s]]',catpref[mo],j,monthg[m]) or '',
y and string.format('[[Category:%s в %s]]',catpref[mo],y,Year0(y,'году')) or ''
},--/table.concat внутр.
(function(F)--возраст
if not F then return '' end;
local n=F();
return n and string.format(" (%i %s)%s",
n,
mw.getLanguage('ru'):plural(n,'год','года','лет'),
n>150 and '[[Category:Википедия:Статьи о персоналиях с большим текущим возрастом]]' or ''
) or ''
end)( ({
['Рождения']=function()
local now=os.date('*t');
if (not d2 or d2=='') and j and m and y then
return Diffy(now.day,now.month,now.year,j,m,y)
end
end,
['Смерти']=function()
return j and m and y and j2 and m2 and y2 and Diffy(j,m,y,j2,m2,y2);
end,
})[mo] ),--конец вызова функции возраста
tail or '',
cat
}--/table.concat внеш.
end;
formdate=function(f) -- Формирует дату по 3--6 параметрам #invoke или шаблона
--не использовать с пустыми аргументами
if (f.args[1] or '')~='' and (f.args[2] or '')~='' or (f.args[3] or '')~='' then
return FormDate(f.args[1],f.args[2],f.args[3],f.args[4],f.args[5],f.args[6],f.args['m'])
else
local tf=f:getParent();
return FormDate(tf.args[1],tf.args[2],tf.args[3],tf.args[4],tf.args[5],tf.args[6],tf.args['m'])
end
end;
cmp=function(f)--Сравнивает две даты, результат соответственно -1, 0 или 1
return Cmp(f.args[1],f.args[2])
end;
G2J=function(f)--перевод григорианских дат в юлианские, возврат DD.MM.YYYY
--Не знает про 15 октября 1582 года, не работает до нашей эры и после ???99 года
--Если есть второй аргумент, преобразует только ДО этой даты включительно
--Если есть третий аргумент, результат форматирует под Персона/Дата
local d,m,y=GetDate(f.args[1])
if f.args[2] and Cmp(f.args[1],f.args[2])==1 then
return string.format("%i.%i.%i",d,m,y)
end
local shift=math.floor(y/100)-math.floor(y/400)-2
if d-shift>0 then
return f.args[3] and string.format("%i.%i.%i (%i)",d,m,y,d-shift)
or string.format("%i.%i.%i",d-shift,m,y)
else
if m==1 then
return f.args[3]
and string.format("%i.1.%i (%i.12.%i)",d,y,31+d-shift,y-1)
or string.format("%i.12.%i",31+d-shift,y-1)
elseif m==3 then
return f.args[3] and string.format("%i.3.%i (%i.2)", d,y,
(y%4==0 and 29 or 28)+d-shift-(y%100==0 and y%400~=0 and 1 or 0)
)
or string.format("%i.2.%i",
(y%4==0 and 29 or 28)+d-shift-(y%100==0 and y%400~=0 and 1 or 0)
,y)
else
return f.args[3] and string.format(
"%i.%i.%i (%i.%i)", d,m,y, monthd[m-1]+d-shift,m-1
)
or string.format("%i.%i.%i",monthd[m-1]+d-shift,m-1,y)
end
end
end;
-- Переводит русскую дату в YYYY-MM-DD. Возвращает входное значение, если дата уже в этом формате
yyyymmdd = function(f)
local date, hourmin = f.args[1]
if mw.ustring.match(date, "^%s*%d+\-%d+\-%d+") then
return date
end
hourmin = mw.ustring.match(date, "%s+%d+:%d+$")
local y, m, d = Yyyymmdd(date)
if not y then
return '<span class="error">Ошибка: некорректный формат даты.</span>'
end
return string.format('%4i-%02i-%02i', y, m, d) .. (hourmin or '')
end
}
function table.val_to_str ( v )
if "string" == type( v ) then
v = string.gsub( v, "\n", "\\n" )
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
return "'" .. v .. "'"
end
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
else
return "table" == type( v ) and table.tostring( v ) or
tostring( v )
end
end
function table.key_to_str ( k )
if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
return k
else
return "[" .. table.val_to_str( k ) .. "]"
end
end
function table.tostring( tbl )
local result, done = {}, {}
for k, v in ipairs( tbl ) do
table.insert( result, table.val_to_str( v ) )
done[ k ] = true
end
for k, v in pairs( tbl ) do
if not done[ k ] then
table.insert( result,
table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
end
end
return "{" .. table.concat( result, "," ) .. "}"
end
local function parseISO8601Date(str)
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local Y, M, D = mw.ustring.match( str, pattern )
return tonumber(Y), tonumber(M), tonumber(D)
end
local function parseISO8601Time(str)
local pattern = "T(%d+):(%d+):(%d+)%Z"
local H, M, S = mw.ustring.match( str, pattern)
return tonumber(H), tonumber(M), tonumber(S)
end
local function parseISO8601Offset(str)
if str:sub(-1)=="Z" then return 0,0 end -- ends with Z, Zulu time
-- matches ±hh:mm, ±hhmm or ±hh; else returns nils
local pattern = "([-+])(%d%d):?(%d?%d?)$"
local sign, oh, om = mw.ustring.match( str, pattern)
sign, oh, om = sign or "+", oh or "00", om or "00"
return tonumber(sign .. oh), tonumber(sign .. om)
end
function p.parseISO8601(str)
if 'table'==type(str) then
if str.args and str.args[1] then
str = '' .. str.args[1]
else
return 'unknown argument type: ' .. type( str ) .. ': ' .. table.tostring( str )
end
end
local Y,M,D = parseISO8601Date(str)
local h,m,s = parseISO8601Time(str)
local oh,om = parseISO8601Offset(str)
return tonumber(os.time({year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s}))
end
local g2uBoundary1 = p.parseISO8601('1582-10-15T00:00:00Z')
local g2uBoundary2 = p.parseISO8601('1700-03-12T00:00:00Z')
local g2uBoundary3 = p.parseISO8601('1800-03-13T00:00:00Z')
local g2uBoundary4 = p.parseISO8601('1900-03-14T00:00:00Z')
local g2uBoundary5 = p.parseISO8601('1918-01-26T00:00:00Z') -- декрет Ленина
-- Передаваемое время обязано быть по Григорианскому календарю (новому стилю)
function p.formatWiki( time, infocardClass, categoryNamePrefix )
if 'table'==type( time ) then
if time.args and time.args[1] then
time = tonumber( time.args[1] )
else
return 'unknown argument type: ' .. type( time ) .. ': ' .. table.tostring( time )
end
end
local t = os.date("*t", time)
if time < g2uBoundary1 then
-- выводим просто юлианский календарь. Задавать тут григорианский некорректно
return p.formatWikiImpl( t, t, infocardClass, categoryNamePrefix )
end
-- Специальные даты
if t.year == 1700 and t.month == 3 and t.day == 11 then
return p.formatWikiImpl( {year=1700, month=2, day=29}, t, infocardClass, categoryNamePrefix)
end
if t.year == 1800 and t.month == 3 and t.day == 12 then
return p.formatWikiImpl( {year=1800, month=2, day=29}, t, infocardClass, categoryNamePrefix )
end
if t.year == 1900 and t.month == 3 and t.day == 13 then
return p.formatWikiImpl( {year=1900, month=2, day=29}, t, infocardClass, categoryNamePrefix )
end
if g2uBoundary1 <= time and time < g2uBoundary2 then
return p.formatWikiImpl( os.date("*t", time - 10 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
end
if g2uBoundary2 <= time and time < g2uBoundary3 then
return p.formatWikiImpl( os.date("*t", time - 11 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
end
if g2uBoundary3 <= time and time < g2uBoundary4 then
return p.formatWikiImpl( os.date("*t", time - 12 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
end
if g2uBoundary4 <= time and time < g2uBoundary5 then
return p.formatWikiImpl( os.date("*t", time - 13 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
end
--только Григорианский календарь
return p.formatWikiImpl( t, t, infocardClass, categoryNamePrefix )
end
local function ternary ( cond , T , F )
if cond then return T else return F end
end
local nominativeMonthes = {'январь', 'февраль', 'март', 'апрель', 'май', 'июнь',
'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'}
local genitivusMonthes = {'января', 'февраля', 'марта', 'апреля', 'мая', 'июня',
'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'}
local function nominativeYear( year, nolinks )
if ( year >= 0 ) then
return nolinks and year or '[[' .. year .. ' год|' .. year .. ']]'
else
return nolinks and ( 0 - year ) .. ' до н. э.' or '[[' .. ( 0 - year ) .. ' год до н. э.|' .. ( 0 - year ) .. ' до н. э.]]'
end
end
local function inYear( year )
if ( year >= 0 ) then
return '' .. year .. ' году'
else
return '' .. ( 0 - year) .. ' году до н. э.'
end
end
function p.formatWikiImpl( t1, t2, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
local nd = t2.day;
local nm = t2.month;
local ny = t2.year;
local od = ternary ( t1.day ~= t2.day , t1.day, nil );
local om = ternary ( t1.month ~= t2.month , t1.month, nil );
local oy = ternary ( t1.year ~= t2.year , t1.year, nil );
if leftBracket == nil then
leftBracket = '('
end
if rightBracket == nil then
rightBracket = ')'
end
local JulianComment = function(s)
return tostring(mw.html.create("abbr")
:attr("title","по юлианскому календарю")
:wikitext(s)
:done())
end
local template =
(nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "") ..
(od ~= nil and "4" or "") .. (om ~= nil and "5" or "") .. (oy ~= nil and "6" or "")
local datePart = '<span class="nowrap">'
if (template == "12") then
datePart = datePart .. string.format( nolinks and "%d %s" or "[[%d %s]]",
nd, genitivusMonthes[nm] )
elseif (template == "23") then
datePart = datePart .. string.format( "%s %s",
nominativeMonthes[nm], nominativeYear( ny, nolinks ) )
elseif (template == "3") then
datePart = datePart .. nominativeYear( ny, nolinks )
elseif (template == "123") then
datePart = datePart .. string.format( nolinks and "%d %s %s" or "[[%d %s]] %s",
nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
elseif (template == "124") then
if nolinks then
datePart = datePart .. JulianComment(string.format( "%d", od )
).. string.format( " " .. leftBracket .. "%d" .. rightBracket .. " %s",
nd, genitivusMonthes[nm] )
else
datePart = datePart .. JulianComment(string.format( "%d", od )
).. string.format( " [[%d %s|" .. leftBracket .. "%d" .. rightBracket .. " %s]]",
nd, genitivusMonthes[nm], nd, genitivusMonthes[nm] )
end
elseif (template == "1234") then
if nolinks then
datePart = datePart .. JulianComment(string.format( "%d", od )
).. string.format( " |" .. leftBracket .. "%d" .. rightBracket .. " %s %s",
nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
else
datePart = datePart .. JulianComment(string.format( "%d", od )
).. string.format( " [[%d %s|" .. leftBracket .. "%d" .. rightBracket .. " %s]] %s",
nd, genitivusMonthes[nm], nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
end
elseif (template == "1245") then
datePart = datePart .. JulianComment(string.format( "%d %s", od, genitivusMonthes[om] )
).. string.format(" " .. leftBracket .. (nolinks and "%d %s" or "[[%d %s]]") .. rightBracket .. "", nd, genitivusMonthes[nm] )
elseif (template == "12345") then
datePart = datePart .. JulianComment(string.format( "%d %s", od, genitivusMonthes[om] )
).. string.format(" " .. leftBracket .. (nolinks and "%d %s" or "[[%d %s]]") .. rightBracket .. " %s", nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
elseif (template == "123456") then
datePart = datePart .. JulianComment(string.format( "%d %s %d", od, genitivusMonthes[om], oy ))
.. '</span> <span class="nowrap">'
.. string.format(" " .. leftBracket .. (nolinks and "%d %s %s" or "[[%d %s]] %s") .. rightBracket , nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
else
datePart = datePart .. 'формат неверен'
end
datePart = datePart .. '</span>'
local infocardTemplate =
(nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "")
if infocardClass then
if (infocardTemplate == "123") then
datePart = datePart .. string.format('<span style="display:none">(<span class="%s">%04d-%02d-%02d</span>)</span>', infocardClass , ny , nm , nd )
elseif (infocardTemplate == "23") then
datePart = datePart .. string.format('<span style="display:none">(<span class="%s">%04d-%02d</span>)</span>', infocardClass , ny , nm )
elseif (infocardTemplate == "3") then
datePart = datePart .. string.format('<span style="display:none;">(<span class="%s">%04d</span>)</span>', infocardClass , ny )
end
end
if categoryNamePrefix then
if ( nd ~= nil and nm ~= nil) then
datePart = datePart .. '[[Category:' .. categoryNamePrefix .. ' ' .. nd .. ' ' .. genitivusMonthes[nm] .. ']]'
end
if ( ny ~= nil) then
datePart = datePart .. '[[Category:' .. categoryNamePrefix .. ' в ' .. inYear( ny ) .. ']]'
end
end
return datePart
end
return p
902bb6a9ef5ce12ad4cfa19f3d2c964d7e092df7
Шаблон:Ombox
10
90
177
2021-10-24T18:05:30Z
wikipedia:ru>Oleg Yunakov
0
Изменил настройки защиты для «[[Шаблон:Ombox]]»: критический шаблон или модуль: https://ru.wikipedia.org/w/index.php?title=Википедия:Установка_защиты&oldid=117401039#Шаблоны ([Редактирование=администраторы и инженеры] (бессрочно) [Переименование=администраторы и инженеры] (бессрочно))
wikitext
text/x-wiki
{{#invoke:Message box|ombox}}<noinclude>
{{doc}}<!-- Add categories and interwikis to the /doc subpage, not here! --></noinclude>
ab34435c5ebc29de589c9b059e88da5d0e6f16e4
Шаблон:Cl
10
92
181
2021-10-26T15:16:40Z
wikipedia:ru>Jack who built the house
0
стилизация на основе [[Модуль:Template call code/styles.css]]
wikitext
text/x-wiki
<templatestyles src="Модуль:Template call code/styles.css" />{{#if: {{{2|}}}
| <span class="ts-templateCallCode-weak"><nowiki>[[</nowiki>Категория:[[:Категория:{{{1}}}|{{{1}}}]]<nowiki>]]</nowiki></span>
| [[:Категория:{{{1}}}|{{{1}}}]]
}}<noinclude>{{doc}}</noinclude>
3f315bb5453e2a3ef5f031e946f35c568b49f8b4
Модуль:Template call code
828
11
19
2021-10-26T19:03:06Z
wikipedia:ru>Jack who built the house
0
-избыточный код
Scribunto
text/plain
local getArgs = require('Module:Arguments').getArgs
local ru = mw.language.new('ru')
local p = {}
-- Используется для того, чтобы можно было удалять элементы из таблицы
local function copy(other)
local res = {}
for k, v in pairs(other) do
res[k] = v
end
return res
end
local function makeInvokeFunc(funcName, flags)
return function (frame)
local args = copy(getArgs(frame, {
trim = false,
removeBlanks = false
}))
return p[funcName](args, flags)
end
end
--предотвращает обработку вики-текста в отображении образца
local function processText(str, nowiki)
local res = str
if nowiki then
str = mw.text.unstripNoWiki(str)
str = string.gsub(str, '%[', '[')
str = string.gsub(str, '%]', ']')
str = string.gsub(str, '<', '<')
str = string.gsub(str, '>', '>')
str = string.gsub(str, '{', '{')
str = string.gsub(str, '|', '|')
str = string.gsub(str, '}', '}')
str = string.gsub(str, '\'', ''')
str = string.gsub(str, '"', '"')
str = string.gsub(str, '(://)', '<span>%1</span>')
end
return str
end
local function addParams(args, params)
local text, equals_pos, param, value = '', 0, '', ''
local function addPipe()
if params.spaced then
text = text .. ' '
end
text = text .. '<span class="'
if not params.spaced then
text = text .. ' ts-templateCallCode-pipe'
end
if not params.black then
text = text .. ' ts-templateCallCode-weak'
end
-- |, чтобы не трактовалось как разделитель ячеек в таблицах
text = text .. '">|</span>'
end
local beforeParam = '<span class="ts-templateCallCode-param">'
local afterParam = '</span>'
for k, v in pairs(args) do
if type(k) == 'number' then -- Неименованные параметры
if k >= params.from then
equals_pos = v:find('=')
if equals_pos and v:find('{{=}}') == equals_pos - 2 then
equals_pos = nil
end
if equals_pos then -- Содержащие «=» преобразуем в именованные
param = v:sub(1, equals_pos - 1)
value = v:sub(equals_pos + 1)
addPipe()
text = text .. beforeParam .. processText(param, params.nowiki) .. '=' .. processText(value, params.nowiki) .. afterParam
else -- Истинно неименованные
addPipe()
local paramValue = processText(v, params.nowiki)
if #paramValue ~= 0 then
text = text .. beforeParam .. paramValue .. afterParam
end
end
end
elseif not k:find('^_') then -- Именованные параметры, исключая модификаторы внешнего вида
addPipe()
text = text .. beforeParam .. processText(k, params.nowiki) .. '=' .. processText(v, params.nowiki) .. afterParam
end
end
return text
end
function p._main(args, flags)
local name = args[1]
table.remove(args, 1)
-- Вещи типа «=» в первом параметре
if not name then
for k, v in pairs(args) do
if not k:find('^_') then
name = k .. '=' .. v
args[k] = nil
break
end
end
end
local optpText
if not flags.withoutParams then
if name then
local spanOffset = mw.ustring.find(name, '<span') -- След использования шаблона optp
if spanOffset then
optpText = mw.ustring.sub(name, spanOffset)
name = mw.ustring.sub(name, 1, spanOffset - 1)
end
end
end
local yesno = require('Module:Yesno')
local nolink, subst, podst, global, nav, noRedirect, ucFirst, black, nobr
local tag, style, comment, lang, sister, global, textInPlaceOfName,
namePrefix, prefix, postfix, nowiki
local spaced, from
if flags.withoutParams then
for i, v in ipairs(args) do
if v == 'nl' or v == 'nolink' then
noLink = true
elseif v == 's' then
subst = true
elseif v == 'п' then
podst = true
elseif v == 'g' then
global = true
elseif v == 'nav' then
nav = true
elseif v == 'noredir' then
noRedirect = true
elseif v == 'u' then
ucFirst = true
elseif v == 'b' then
black = true
elseif v == 'nobr' then
nobr = true
end
end
tag = args.tag or 'span'
style = args.style
comment = args.comment
lang = args.lang
sister = args.sister
textInPlaceOfName = args.text
namePrefix = args.nameprefix
prefix = args.prefix
postfix = args.postfix
nowiki = args.nowiki
else
noLink = yesno(args._nolink or args._nl, false) or not yesno(args._link, false)
subst = yesno(args._s, false)
podst = yesno(args['_п'], false)
global = yesno(args._g, false)
nav = yesno(args._nav, false)
noRedirect = yesno(args._noredir, false)
ucFirst = yesno(args._u, false)
black = yesno(args._b, false)
nobr = yesno(args._nobr, false)
tag = args._tag or 'span'
style = args._style
comment = args._comment
lang = args._lang
sister = args._sister
textInPlaceOfName = args._text
namePrefix = args._nameprefix
prefix = args._prefix
postfix = args._postfix
nowiki = args._nowiki
spaced = yesno(args._spaced, false)
from = (tonumber(args._from) or 2) - 1
end
global = global or name and mw.ustring.sub(name, 1, 1) == ':'
black = black or tag ~= 'span'
if textInPlaceOfName == '' then
textInPlaceOfName = nil
end
if comment == '' then
comment = nil
end
if lang == '' then
lang = nil
end
if sister == '' then
sister = nil
end
if namePrefix == '' then
namePrefix = nil
end
if name then
local trimmedName = mw.text.trim(name)
if ru:lc(mw.ustring.sub(trimmedName, 1, 6)) == 'subst:' then
subst = true
name = mw.ustring.sub(trimmedName, 7)
end
if ru:lc(mw.ustring.sub(trimmedName, 1, 6)) == 'подст:' then
podst = true
name = mw.ustring.sub(trimmedName, 7)
end
end
if subst then
namePrefix = 'subst:'
elseif podst then
namePrefix = 'подст:'
end
local currentTitle = mw.title.getCurrentTitle()
-- При опущенном первом параметре берём имя шаблона из названия страницы
if name == '' or not name then
local currentTitleRoot = currentTitle.rootText
if not ucFirst and
(
(
ru:uc(currentTitleRoot) ~= currentTitleRoot and
-- Книга:Литературное наследство, TranslateDate
not mw.ustring.match(currentTitleRoot, '^[А-Яа-яA-Za-z]+:?[А-ЯA-Z]')
) or
#currentTitleRoot == 1
)
then
name = ru:lcfirst(currentTitleRoot)
else
name = currentTitleRoot
end
end
-- Начинаем собирать код
local linkBody, titleObject, linkBegin, linkDivider, linkEnd
local prefixes = {}
if lang then
table.insert(prefixes, lang)
end
if sister then
table.insert(prefixes, sister)
end
linkBody = table.concat(prefixes, ':')
if #linkBody ~= 0 then
linkBody = ':' .. linkBody
end
if mw.ustring.sub(name, 1, 1) ~= ':' then
linkBody = linkBody .. ':'
end
if not global then
linkBody = linkBody .. 'Template:'
end
linkBody = linkBody .. name
titleObject = mw.title.new(linkBody)
local noLink = noLink or currentTitle == titleObject
if not noLink then
if not noRedirect or (
noRedirect and
not lang and
not sister and
not titleObject.exists
) then
linkBegin = '[['
linkEnd = ']]'
linkDivider = '|'
else
linkBegin = '['
linkEnd = ']'
linkDivider = ' '
linkBody = titleObject:fullUrl('redirect=no')
end
end
local text = ''
if tag then
text = text .. '<' .. tag .. ' class="ts-templateCallCode'
if nobr then
text = text .. ' nowrap'
end
text = text .. '"'
if style then
text = text .. ' style="' .. style .. '"'
end
text = text .. '>'
end
if prefix then
text = text .. processText(prefix, nowiki)
end
text = text .. '<span class="'
if not spaced then
text = text .. ' ts-templateCallCode-opening'
end
if not black then
text = text .. ' ts-templateCallCode-weak'
end
text = text .. '">{{'
if namePrefix then
text = text .. namePrefix
end
text = text .. '</span>'
if nav and currentTitle == titleObject then
text = text .. '\'\'\''
end
text = text .. '<span class="ts-templateCallCode-templateName" data-navboxnavigation-link="0">'
local commentedLabel
if comment then
-- https://phabricator.wikimedia.org/T200704
-- commentedLabel = mw.getCurrentFrame():expandTemplate({title = 'comment', args = {(textInPlaceOfName or name), comment}})
commentedLabel = '<span class="commentedText" title="' .. comment .. '" style="border-bottom: 1px dotted; cursor: help;">' ..
(textInPlaceOfName or name) ..
'</span>'
end
local label = (commentedLabel or textInPlaceOfName or name)
if not noLink then
if noRedirect then
text = text .. '<span class="plainlinks">'
end
text = text .. linkBegin .. linkBody .. linkDivider .. label .. linkEnd
if noRedirect then
text = text .. '</span>'
end
else
text = text .. label
end
text = text .. '</span>'
if nav and currentTitle == titleObject then
text = text .. '\'\'\''
end
if not flags.withoutParams then
if optpText then
text = text .. optpText
end
text = text .. addParams(args, {
spaced = spaced,
black = black,
nowiki = nowiki,
from = from
})
if spaced then
text = text .. ' '
end
end
text = text .. '<span class="'
if not spaced then
text = text .. ' ts-templateCallCode-closing'
end
if not black then
text = text .. ' ts-templateCallCode-weak'
end
text = text .. '">}}</span>'
if postfix then
text = text .. processText(postfix, nowiki)
end
if tag then
text = text .. '</' .. tag .. '>'
end
local ts = mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Модуль:Template call code/styles.css' } }
return ts .. text
end
function p._onlyParams(args)
local yesno = require('Module:Yesno')
return addParams(args, {
spaced = yesno(args._spaced, false),
black = true,
nowiki = yesno(args._nowiki, false),
from = 1
})
end
p.withoutParams = makeInvokeFunc('_main', {withoutParams = true})
p.withParams = makeInvokeFunc('_main', {withoutParams = false})
p.onlyParams = makeInvokeFunc('_onlyParams')
return p
c4cde66869b509219e9bf629a766ce30ad0bdf97
Шаблон:C
10
96
189
2021-11-05T11:44:04Z
wikipedia:ru>GAndy
0
Изменил настройки защиты для «[[Шаблон:C]]»: понижение защиты согласно количеству включений (больше 2000, меньше 5000) ([Редактирование=только автоподтверждённые] (бессрочно) [Переименование=только автоподтверждённые] (бессрочно))
wikitext
text/x-wiki
{{#switch: {{{2}}}
| Р = {{{к|к}}}атегории
| Д = {{{к|к}}}атегории
| В = {{{к|к}}}атегорию
| Т = {{{к|к}}}атегорией
| П = {{{к|к}}}атегории
| ю = {{{к|к}}}атегорию
| ей | й = {{{к|к}}}атегорией
| и = {{{к|к}}}атегории
| {{{к|к}}}атегория
}} «[[:Категория:{{{1}}}|{{вложенные кавычки|{{{1}}}}}]]»<noinclude>{{doc}}</noinclude>
29dc241d0737db87ea05ae164b21b3bdc0da3f83
Модуль:Template call code/styles.css
828
13
23
2021-11-15T10:35:51Z
wikipedia:ru>Jack who built the house
0
поддержка [[t:optp]] (например, на [[Модуль:Unsubst/doc]])
text
text/plain
.ts-templateCallCode-weak {
color: #72777d;
}
.ts-templateCallCode-pipe {
margin: 0 2px;
}
.ts-templateCallCode-pipe + .ts-templateCallCode-pipe,
/* Template:Optp */
.ts-templateCallCode-pipe + .ts-templateCallCode-param > .ts-templateCallCode-weak:first-child > .ts-templateCallCode-pipe:first-child {
margin-left: 0;
}
.ts-templateCallCode-param + .ts-templateCallCode-closing {
margin-left: 2px;
}
span.ts-templateCallCode > .ts-templateCallCode-templateName a {
/* Решение из https://ru.wikipedia.org/wiki/Шаблон:Фиттс */
padding: 0 0.5em !important; /* Перезаписываем стиль для .plainlinks a.external */
position: relative;
margin: -0.5em;
}
/* [[Категория:Шаблоны:Подстраницы CSS]] */
b3ed166240cf28c48a58b8d992794b753b2c6ef5
Шаблон:Lang-en
10
62
121
2022-01-02T12:52:08Z
wikipedia:ru>Abiyoyo
0
замена редиректа прямым включением
wikitext
text/x-wiki
<nowiki />[[английский язык|англ.]] {{lang-en2|{{{1}}}}}<noinclude>
{{doc|Lang/doc}}
</noinclude>
6fcc1d4dc63f133033671bf27e48a6e701e126cb
Шаблон:Карточка
10
24
45
2022-04-03T23:49:38Z
wikipedia:ru>Putnik
0
пробуем красить каждую карточку на странице отдельно, без перекрытия стилей; надеюсь, комбинация имя+вверху0+вверху+вверху2 достаточно уникальна и не вызовет ошибок
wikitext
text/x-wiki
{{#if:{{{имя|}}}|{{#ifeq:{{{имя|}}}|-||{{#if:{{{цвет|}}}|{{#tag:templatestyles|
|wrapper=.infobox-{{#invoke:Hash|main|{{{имя}}} {{{вверху0|}}} {{{вверху|}}} {{{вверху2|}}}}}
|src=Шаблон:Цвет/{{{цвет|}}}.css
}}}}}}}}<table class="infobox infobox-{{#invoke:Hash|main|{{{имя}}} {{{вверху0|}}} {{{вверху|}}} {{{вверху2|}}}}} {{{класс_тела|}}}" style="{{{стиль_тела|}}}" {{#if:{{{имя|}}}|{{#ifeq:{{{имя|}}}|-||data-name="{{{имя}}}"}}}} {{#if:{{{from|}}}|{{#ifeq:{{{from|}}}|-||data-from="{{{from}}}"}}}}><!--
Вверху0
-->{{#if:{{{вверху0|}}}|<tr><td colspan="2" class="{{{класс_вверху0|}}}" style="text-align:center; {{{стиль_вверху0|}}}">{{{вверху0}}}</td></tr>}}<!--
Вверху
-->{{#if:{{{вверху|}}}|<tr><th colspan="2" scope="colgroup" class="infobox-above {{{класс_вверху|}}}" style="{{{стиль_вверху|}}}">{{{вверху}}}</th></tr>}}<!--
Вверху2
-->{{#if:{{{вверху2|}}}|<tr><td colspan="2" class="{{{класс_вверху2|}}}" style="text-align:center; {{{стиль_вверху2|}}}">{{{вверху2}}}</td></tr>}}<!--
Вверху3
-->{{#if:{{{вверху3|}}}|<tr><td colspan="2" class="{{{класс_вверху3|}}}" style="text-align:center; {{{стиль_вверху3|}}}">{{{вверху3}}}</td></tr>}}<!--
Изображение
-->{{#if:{{{изображение|}}}|<tr><td colspan="2" class="infobox-image {{{класс_изображения|}}}" style="{{{стиль_изображения|}}}"> {{{изображение}}} {{#if:{{{подпись|}}}|
<div class="media-caption" style="{{{стиль_подписи|}}}">{{{подпись}}}</div>}}</td></tr>}}<!--
Изображение2
-->{{#if:{{{изображение2|}}}|<tr><td colspan="2" class="infobox-image {{{класс_изображения2|}}}" style="{{{стиль_изображения2|}}}"> {{{изображение2}}} {{#if:{{{подпись2|}}}|
<div class="media-caption" style="{{{стиль_подписи2|}}}">{{{подпись2}}}</div>}}</td></tr>}}<!--
Изображение3
-->{{#if:{{{изображение3|}}}|<tr><td colspan="2" class="infobox-image {{{класс_изображения3|}}}" style="{{{стиль_изображения3|}}}"> {{{изображение3}}} {{#if:{{{подпись3|}}}|
<div class="media-caption" style="{{{стиль_подписи3|}}}">{{{подпись3}}}</div>}}</td></tr>}}<!--
Строки
-->{{#invoke:Infobox|renderLines}}<!--
Внизу
-->{{Карточка/внизу|
стиль_внизу_общий={{{стиль_внизу|}}}|
класс_внизу={{{класс_внизу|}}}|
внизу={{{внизу|}}}}}<!--
Внизу N
-->{{#invoke:Transclude|npc|Карточка/внизу|
стиль_внизу_общий={{{стиль_внизу|}}}|
стиль_внизу=|
класс_внизу=|
внизу=}}
</table><includeonly><!--
статьи
-->{{#if:{{NAMESPACE}}||<!--
-->{{#if:{{{имя|}}}||[[Категория:Статьи с шаблонами-карточками без имени]]}}<!--
-->{{#ifeq:{{{имя|}}}|{{subst:PAGENAME}}|[[Категория:Статьи с шаблонами-карточками без имени]]}}<!--
-->}}<!--
шаблоны
-->{{#ifeq:{{NAMESPACENUMBER}}|10|<!--
-->{{#if:{{{имя|}}}||[[Категория:Шаблоны-карточки без имени]]}}<!--
-->{{#ifeq:{{{имя|}}}|{{subst:PAGENAME}}|[[Категория:Шаблоны-карточки без имени]]}}<!--
-->{{#if:{{{название|}}}{{{стиль_названия|}}}|[[Категория:Шаблоны с использованием параметра «название» в шаблоне «Карточка»]]}}<!--
-->{{#if:{{{подпись|}}}{{{стиль_подписи|}}}{{{подпись2|}}}{{{стиль_подписи2|}}}{{{подпись3|}}}{{{стиль_подписи3|}}}|[[Категория:Шаблоны с использованием параметра «подпись» в шаблоне «Карточка»]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_тела|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_названия|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_вверху|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_вверху2|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_вверху3|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_подписи|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_подписи2|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_подписи3|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_заголовков|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_меток|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_текста|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_внизу|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifeq:{{{имя|}}}|{{PAGENAME}}|<!--
-->[[Категория:Шаблоны-карточки по алфавиту|{{ucfirst:{{без начала|{{PAGENAME}}|Карточка }}}}]]<!--
-->{{#if:{{{стиль_тела|}}}{{{стиль_вверху|}}}{{{стиль_заголовков|}}}{{{стиль_внизу|}}}|[[Категория:Википедия:Шаблоны-карточки с явным указанием стилей]]}}<!--
-->}}<!--
-->}}<!--
любое пространство имён
-->{{#if:{{{название|}}}{{{стиль_названия|}}}|[[Категория:Википедия:Страницы с использованием параметра «название» в шаблоне «Карточка»]]}}<!--
-->{{#if:{{{подпись|}}}{{{стиль_подписи|}}}{{{подпись2|}}}{{{стиль_подписи2|}}}{{{подпись3|}}}{{{стиль_подписи3|}}}|[[Категория:Википедия:Страницы с использованием параметра «подпись» в шаблоне «Карточка»]]}}</includeonly><noinclude>{{doc}}</noinclude>
5bd0cadc0cad51dc109de7db63622ab36743d386
Шаблон:Карточка/Викисклад
10
27
51
2022-04-30T14:39:04Z
wikipedia:ru>ShinePhantom
0
еще одна проверочная категория для зачистки
wikitext
text/x-wiki
{{wikidata|p373|{{str rep|{{str rep|{{{1|}}}|Category:|}}|category:|}}|plain=false|text=Медиафайлы на Викискладе|icon={{{icon|}}}|icon_size={{{icon_size|}}}|from={{{from|}}}}}<!--
-->{{#if: {{{nocat|}}}{{NAMESPACE}} || <!--
-->{{#if: {{{1|}}} | [[Категория:Википедия:Ссылка на Викисклад непосредственно в статье]]<!--
-->{{#if: {{wikidata|p373|plain=true}}
| {{#ifeq: {{str rep|{{str rep|{{{1|}}}|Category:|}}|category:|}} | {{wikidata|p373|plain=true}} |[[Категория:Википедия:Ссылки на Викисклад в статье и на Викиданных совпадают]]| [[Категория:Википедия:Ссылки на Викисклад в статье и на Викиданных отличаются]] }}
| [[Категория:Википедия:Ссылка на Викисклад в статье, но не на Викиданных]]
}} }}<!--
--> }}<!--
-->{{#ifeq: {{NAMESPACE}} | Шаблон | {{#if: {{{2|}}} | [[Категория:Википедия:Шаблоны для низа карточек с лишним параметром]] }} }}<!--
--><noinclude>
{{doc}}
</noinclude>
40ef9a463c772ddbf54feae9e21d4037b692253e
Шаблон:Флагификация/Германия
10
70
137
2022-10-16T05:50:42Z
wikipedia:ru>Well-Informed Optimist
0
уточнение
wikitext
text/x-wiki
{{ {{{1<noinclude>|флагификация/флаг</noinclude>}}}
| alias = Германия
| flag alias = Flag of Germany.svg
| flag alias-империя = Flag of the German Empire.svg
| flag alias-1871 = Flag of the German Empire.svg
| flag alias-1919 = Flag of Germany (2-3).svg
| flag alias-1933-1 = National flag of Germany 1933-1935.svg
| flag alias-1933 = Flag of German Reich (1935–1945).svg
| flag alias-1946 = Flag of Germany (1946-1949).svg
| flag alias-Берлин = Flag of Berlin.svg
| flag alias-ГДР = Flag of East Germany.svg
| flag alias-1938 = War Ensign of Germany 1938-1945.svg
| flag alias-ВМФ = Naval Ensign of Germany.svg
| flag alias-1892 = Kaiserliche Kriegsflagge (1892).png
| flag alias-1921 = War Ensign of Germany (1921–1933).svg
| var1 = империя
| var2 = 1871
| var3 = 1919
| var4 = 1933-1
| var5 = 1933
| var6 = 1946
| var7 = Берлин
| var8 = ГДР
| var9 = 1938
| var10 = ВМФ
| var11 = 1892
| var12 = 1921
| variant = {{{variant|}}}
| размер = {{{размер|}}}
}}
efa3b6861970635c792254f5da10e4efbc3ded5d
Шаблон:Музыкант/цвет/схема
10
99
195
2023-04-27T01:30:31Z
wikipedia:ru>Oleg Yunakov
0
Защитил страницу [[Шаблон:Музыкант/цвет/схема]]: критический шаблон или модуль: используется на 29 522 страницах ([Редактирование=администраторы и инженеры] (бессрочно) [Переименование=администраторы и инженеры] (бессрочно))
wikitext
text/x-wiki
<includeonly>{{#switch:{{lc:{{{1|}}}}}<!--
-->|solo_singer |вокалист=Вокалист<!--
-->|non_vocal_instrumentalist |инструменталист=Инструменталист<!--
-->|non_performing_personnel |композитор |продюсер |дирижёр=Композитор<!--
-->}}</includeonly><noinclude>
{{doc}}
</noinclude>
0fc69c91f5ef446372370b02ac2ddf786f06c3d5
Модуль:Wikidata/url
828
77
151
2023-05-09T00:51:03Z
wikipedia:ru>Putnik
0
оптимизация потребления памяти за счёт замены mw.wikibase.getEntity() на mw.wikibase.getBestStatements()
Scribunto
text/plain
local p = {}
local function formatLangRefs( options )
local langRefs = {}
if options.qualifiers and options.qualifiers.P407 then
for _, qualifier in ipairs( options.qualifiers.P407 ) do
if ( qualifier
and qualifier.datavalue
and qualifier.datavalue.type == 'wikibase-entityid' ) then
local qualifierId = qualifier.datavalue.value.id
local wbStatus, langRefCodeClaims = pcall( mw.wikibase.getBestStatements, qualifierId, 'P218' )
if wbStatus and langRefCodeClaims then
for _, claim in ipairs( langRefCodeClaims ) do
if ( claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.type == 'string' ) then
local langRefCode = claim.mainsnak.datavalue.value
table.insert( langRefs, options.frame:expandTemplate{ title = 'ref-' .. langRefCode } )
end
end
end
end
end
end
return table.concat( langRefs, '​' )
end
function p.formatUrlValue( context, options, value )
local moduleUrl = require( 'Module:URL' )
local langRefs = formatLangRefs( options )
if not options.length or options.length == '' then
options.length = math.max( 18, 25 - #langRefs )
end
return moduleUrl.formatUrlSingle( context, options, value ) .. langRefs
end
return p
4a9959f45666b35899729e561a73e0535c16e15e
Модуль:WikidataSelectors
828
33
63
2023-05-09T18:46:16Z
wikipedia:ru>Putnik
0
исправление метода load()
Scribunto
text/plain
local i18n = {
["errors"] = {
["rank-not-valid"] = "Некорретное значение приоритета (rank)",
["cant-parse-condition"] = "Не удалось разобрать условие"
}
}
local validRanks = {
'best',
'preferred',
'normal',
'deprecated'
}
--[[
Internal function for error message
Input: key in errors table
Output: error message
]]
local function throwError( key )
error( i18n.errors[key] )
end
local p = {}
--[[
Load property and filter statements
Input: entityId, selector string
Output: filtered statements table
]]
function p.load( entityId, propertySelector )
local propertyId = mw.ustring.match( propertySelector, '^[Pp]%d+' )
if not propertyId then
return nil
end
propertyId = string.upper( propertyId )
local allStatements = {}
allStatements[ propertyId ] = mw.wikibase.getAllStatements( entityId, propertyId )
return p.filter( allStatements, propertySelector )
end
--[[
Parse selectors and filter statements
Input: statements table, selector string
Output: filtered statements table
]]
function p.filter( allClaims, propertySelector )
propertySelector = mw.text.trim( propertySelector )
-- Get property ID from selector
local propertyId = mw.ustring.match( propertySelector, '^[Pp]%d+' )
if not propertyId then
propertyId = ''
end
local initPos = #propertyId + 1
propertyId = string.upper( propertyId )
if ( not allClaims ) then
return nil
end
local allPropertyClaims = allClaims[propertyId]
if ( not allPropertyClaims ) then
return nil
end
-- Gathering rules
local rules = p.matchSelectors( propertySelector, initPos )
-- If there is no rank filter, than default rank is 'best'
local isRanked = false
for i, subRules in ipairs( rules ) do
for j, rule in ipairs( subRules ) do
if rule['type'] == 'rank' then
isRanked = true
break
end
end
end
if not isRanked then
table.insert( rules, 1, { { type = 'rank', value = 'best' } } )
end
-- Execute rules
allPropertyClaims = p.applyRules( allPropertyClaims, rules )
return allPropertyClaims
end
--[[
Match and gather selector rules
Input: string with selectors rules, start position
Output: rules table
]]
function p.matchSelectors( selectorsString, initPos )
local rules = {}
local rawRulePattern = '^%s*%[%s*[^%[%]]+%s*%]%s*'
local rulePattern = '^%s*%[%s*([^%[%]]+)%s*%]%s*$'
if not initPos then
initPos = 1
end
local rawRule = mw.ustring.match( selectorsString, rawRulePattern, initPos )
while rawRule do
initPos = initPos + #rawRule
rule = mw.ustring.match( rawRule, rulePattern )
rule = mw.text.trim( rule )
local subRules = mw.text.split( rule, '%s*,%s*' )
local commands = {}
local comm
for i, subRule in ipairs( subRules ) do
local isInversed = false
if mw.ustring.match( subRule, '^!' ) then
isInversed = true
subRule = mw.ustring.match( subRule, '^!%s*(.+)$' )
end
-- p123[1]
if mw.ustring.match( subRule, '^%d+$' ) then
table.insert( commands, {
type = 'position',
value = subRule,
inversed = isInversed
} )
-- p123[rank:preferred]
elseif mw.ustring.match( subRule, '^rank%s*:%s*(%a+)$' ) then
rank = mw.ustring.match( subRule, '^rank%s*:%s*(%a+)$' )
table.insert( commands, {
type = 'rank',
value = rank,
inversed = isInversed
} )
-- p123[language:xx]
elseif mw.ustring.match( subRule, '^language%s*:%s*([%a%-]+)$' ) then
value = mw.ustring.match( subRule, '^language%s*:%s*([%a%-]+)$' )
table.insert( commands, {
type = 'language',
value = value,
inversed = isInversed
} )
-- p123[language!:xx]
elseif mw.ustring.match( subRule, '^language%s*!:%s*([%a%-]+)$' ) then
value = mw.ustring.match( subRule, '^language%s*!:%s*([%a%-]+)$' )
table.insert( commands, {
type = 'language',
value = value,
inversed = not isInversed
} )
-- p123[min]
elseif mw.ustring.match( subRule, '^min$' ) then
table.insert( commands, { type = 'value_min' } )
-- p123[max]
elseif mw.ustring.match( subRule, '^max$' ) then
table.insert( commands, { type = 'value_max' } )
-- p123[min:p456]
elseif mw.ustring.match( subRule, '^min%s*:%s*[Pp]%d+$' ) then
value = mw.ustring.match( subRule, ':%s*([Pp]%d+)$' )
table.insert( commands, {
type = 'qualifier_min',
qualifier = value
} )
-- p123[max:p456]
elseif mw.ustring.match( subRule, '^max%s*:%s*[Pp]%d+$' ) then
value = mw.ustring.match( subRule, ':%s*([Pp]%d+)$' )
table.insert( commands, {
type = 'qualifier_max',
qualifier = value
} )
-- p123[unit:q789]
elseif mw.ustring.match( subRule, '^unit%s*:%s*[^%[%],:]+$' ) then
value = mw.ustring.match( subRule, ':%s*([^%[%],:]+)$' )
table.insert( commands, {
type = 'unit',
value = value,
inversed = isInversed
} )
-- p123[unit!:q789]
elseif mw.ustring.match( subRule, '^unit%s*!:%s*[^%[%],:]+$' ) then
value = mw.ustring.match( subRule, '!:%s*([^%[%],:]+)$' )
table.insert( commands, {
type = 'unit',
value = value,
inversed = not isInversed
} )
-- p123[p456]
elseif mw.ustring.match( subRule, '^[Pp]%d+$' ) then
qualifier = mw.ustring.match( subRule, '^[Pp]%d+' )
table.insert( commands, {
type = 'qualifier',
qualifier = qualifier,
value = nil,
inversed = isInversed
} )
-- p123[p456:q789]
elseif mw.ustring.match( subRule, '^[Pp]%d+%s*:%s*[^%[%],:]+$' ) then
qualifier = mw.ustring.match( subRule, '^([Pp]%d+)%s*:?' )
value = mw.ustring.match( subRule, ':%s*([^%[%],:]+)$' )
table.insert( commands, {
type = 'qualifier',
qualifier = qualifier,
value = value,
inversed = isInversed
} )
-- p123[p456!:q789]
elseif mw.ustring.match( subRule, '^[Pp]%d+%s*!:%s*[^%[%],:]+$' ) then
qualifier = mw.ustring.match( subRule, '^([Pp]%d+)%s*!:?' )
value = mw.ustring.match( subRule, '!:%s*([^%[%],:]+)$' )
table.insert( commands, {
type = 'qualifier',
qualifier = qualifier,
value = value,
inversed = not isInversed
} )
-- p123[q456]
elseif mw.ustring.match( subRule, '^[Qq]%d+$' ) then
value = mw.ustring.match( subRule, '^[Qq]%d+' )
table.insert( commands, {
type = 'value',
value = value,
inversed = isInversed
} )
else
throwError( 'cant-parse-condition' )
end
end
if #commands then
table.insert( rules, commands )
end
rawRule = mw.ustring.match( selectorsString, rawRulePattern, initPos )
end
return rules
end
--[[
Intercept statements with selector rules
Input: statements table, selector rules
Output: filtered statements table
]]
function p.applyRules( claims, rules )
for i, subRules in ipairs( rules ) do
local newClaims = {}
for j, rule in ipairs( subRules ) do
if rule['type'] == 'rank' then
table.insert( newClaims, p.filterByRank( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'language' then
table.insert( newClaims, p.filterByLanguage( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'unit' then
table.insert( newClaims, p.filterByUnit( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'position' then
table.insert( newClaims, p.filterByPosition( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'qualifier' then
table.insert( newClaims, p.filterByQualifier( claims, rule['qualifier'], rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'qualifier_min' then
table.insert( newClaims, p.filterUtterByQualifier( claims, rule['qualifier'], true ) )
elseif rule['type'] == 'qualifier_max' then
table.insert( newClaims, p.filterUtterByQualifier( claims, rule['qualifier'], false ) )
elseif rule['type'] == 'value' then
table.insert( newClaims, p.filterByValue( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'value_min' then
table.insert( newClaims, p.filterUtter( claims, true ) )
elseif rule['type'] == 'value_max' then
table.insert( newClaims, p.filterUtter( claims, false ) )
end
end
claims = {}
--[[
Merge all claims
TODO: It's not good
]]
for j, newSubClaims in ipairs( newClaims ) do
for k, newClaim in ipairs( newSubClaims ) do
local isNew = true
for l, oldClaim in ipairs( claims ) do
if oldClaim['id'] == newClaim['id'] then
isNew = false
break
end
end
if isNew then
table.insert( claims, newClaim )
end
end
end
end
return claims
end
--[[
Filter statements by rank
Input: claims table, rank value, inversion
Output: filtered statements table
]]
function p.filterByRank( claims, rank, inversed )
if not inversed then
inversed = false
end
if not rank then
rank = 'best'
end
-- Check if rank value is valid
local isValidRank = false
for i, validRank in ipairs( validRanks ) do
if rank == validRank then
isValidRank = true
break
end
end
if not isValidRank then
throwError( 'rank-not-valid' )
end
-- Find the best rank
if rank == 'best' then
rank = 'normal' -- default rank (don't use deprecated even if it's no more claims)
-- If we have at least one preferred rank, mark it as best
for i, statement in pairs( claims ) do
if (statement.rank == 'preferred') then
rank = 'preferred'
break
end
end
end
local resultClaims = {};
for i, statement in pairs( claims ) do
if ( statement.rank == rank ) ~= inversed then
table.insert( resultClaims, statement )
end
end
return resultClaims
end
--[[
Filter statements by language of value
Input: claims table, language, inversion
Output: filtered statements table
]]
function p.filterByLanguage( claims, language, inversed )
if not inversed then
inversed = false
end
local resultClaims = {}
local mulStatement = {}
for i, statement in ipairs( claims ) do
isMatchLanguage = false
if statement['mainsnak']
and statement['mainsnak']['datavalue']
and statement['mainsnak']['datavalue']['value']
and statement['mainsnak']['datavalue']['value']['language'] then
if statement['mainsnak']['datavalue']['value']['language'] == language then
isMatchLanguage = true
end
if statement['mainsnak']['datavalue']['value']['language'] == 'mul' then
mulStatement = statement
end
end
if isMatchLanguage ~= inversed then
table.insert( resultClaims, statement )
end
end
if next(resultClaims) == nil and next(mulStatement) ~= nil then
-- if specific language is not found, but there is Q20923490 value
table.insert( resultClaims, mulStatement )
end
return resultClaims
end
--[[
Filter statements by unit of value
Input: claims table, unit, inversion
Output: filtered statements table
]]
function p.filterByUnit( claims, unit, inversed )
if not inversed then
inversed = false
end
unit = 'http://www.wikidata.org/entity/' .. string.upper( unit )
local resultClaims = {}
for i, statement in ipairs( claims ) do
isMatchUnit = false
if statement['mainsnak']
and statement['mainsnak']['datavalue']
and statement['mainsnak']['datavalue']['value']
and statement['mainsnak']['datavalue']['value']['unit']
and statement['mainsnak']['datavalue']['value']['unit'] == unit then
isMatchUnit = true
end
if isMatchUnit ~= inversed then
table.insert( resultClaims, statement )
break
end
end
return resultClaims
end
--[[
Filter statements by position
Input: claims table, position, inversion
Output: filtered statements table
]]
function p.filterByPosition( claims, position, inversed )
if not inversed then
inversed = false
end
local resultClaims = {};
for statementPosition, statement in ipairs( claims ) do
if ( statementPosition == tonumber( position ) ) ~= inversed then
table.insert( resultClaims, statement )
break
end
end
return resultClaims
end
--[[
Filter statements by qualifier existance or it's value
Input: claims table, ID of qualifier's property, qualifier's value, inversion
Output: filtered statements table
]]
function p.filterByQualifier( claims, qualifierId, value, inversed )
if not inversed then
inversed = false
end
qualifierId = string.upper( qualifierId )
local resultClaims = {}
for i, statement in ipairs( claims ) do
if statement['qualifiers'] and statement['qualifiers'][qualifierId] then
if value == nil then
if ( #statement['qualifiers'][qualifierId] > 0 ) ~= inversed then
table.insert( resultClaims, statement )
end
else
local isQualifierFound = false
for j, qualifier in ipairs( statement['qualifiers'][qualifierId] ) do
if qualifier['datavalue'] then
local qualifierValue = qualifier['datavalue']['value']
if qualifier['datavalue']['type'] == 'wikibase-entityid' then
qualifierValue = qualifierValue.id
value = string.upper( value )
end
if qualifierValue == value then
isQualifierFound = true
break
end
end
end
if isQualifierFound ~= inversed then
table.insert( resultClaims, statement )
end
end
elseif inversed then
table.insert( resultClaims, statement )
end
end
return resultClaims
end
--[[
Filter statements by it's values
Input: claims table, value, inversed
Output: filtered statements table
]]
function p.filterByValue( claims, value, inversed )
inversed = inversed or false
local resultClaims = {}
for i, statement in ipairs( claims ) do
local statementValue
if statement['mainsnak']
and statement['mainsnak']['datavalue']
and statement['mainsnak']['datavalue']['type']
then
statementValue = statement['mainsnak']['datavalue']['value']
if statement['mainsnak']['datavalue']['type'] == 'quantity' then
statementValue = statementValue.amount
end
if statement['mainsnak']['datavalue']['type'] == 'time' then
statementValue = statementValue.time
end
if statement['mainsnak']['datavalue']['type'] == 'wikibase-entityid' then
statementValue = statementValue.id
value = string.upper( value )
end
end
if ( statementValue == value ) ~= inversed then
table.insert( resultClaims, statement )
end
end
return resultClaims
end
--[[
Find a statement with minimum or maximum value
Input: claims table, asc, inversed
Output: filtered statements table
]]
function p.filterUtter( claims, asc, inversed )
local resultValue = nil
for i, statement in ipairs( claims ) do
local statementValue
if statement['mainsnak'] and
statement['mainsnak']['datavalue'] and
statement['mainsnak']['datavalue']['type']
then
statementValue = statement['mainsnak']['datavalue']['value']
if statement['mainsnak']['datavalue']['type'] == 'quantity' then
statementValue = statementValue.amount
end
if statement['mainsnak']['datavalue']['type'] == 'time' then
statementValue = statementValue.time
end
if statement['mainsnak']['datavalue']['type'] == 'wikibase-entityid' then
statementValue = statementValue.id
end
if not resultValue or ( statementValue < resultValue ) == asc then
resultValue = statementValue
end
end
end
mw.logObject( resultValue, 'resultValue' )
return p.filterByValue( claims, resultValue, inversed )
end
--[[
Find a statement with minimum or maximum qualifier value
Input: claims table, qualifierId, asc
Output: filtered statements table
]]
function p.filterUtterByQualifier( claims, qualifierId, asc )
qualifierId = string.upper( qualifierId )
local resultValue = nil
local resultStatement = nil
for i, statement in ipairs( claims ) do
if not statement['qualifiers'] and not statement['qualifiers'][qualifierId] then
if resultStatement == nil then
resultStatement = statement
end
else
for _, qualifier in ipairs( statement['qualifiers'][qualifierId] ) do
if qualifier['datavalue'] then
local qualifierValue = qualifier['datavalue']['value']
if qualifier['datavalue']['type'] == 'quantity' then
qualifierValue = qualifierValue.amount
end
if qualifier['datavalue']['type'] == 'time' then
qualifierValue = qualifierValue.time
end
if qualifier['datavalue']['type'] == 'wikibase-entityid' then
qualifierValue = qualifierValue.id
end
if not resultValue or ( qualifierValue < resultValue ) == asc then
resultStatement = statement
resultValue = qualifierValue
end
end
end
end
end
return { resultStatement }
end
return p
0bdff3a63bf171160cdec5c966211fbbf3003880
Модуль:Calendar
828
16
29
2023-05-17T17:44:45Z
wikipedia:ru>Dima st bk
0
+ короткие варианты для английского, см. [[Обсуждение шаблона:Cite web#Формат параметра %7Carchive-date=]]
Scribunto
text/plain
local p = {}
-- Необходимые модули и переменные
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local mwlang = mw.getContentLanguage()
local err = "―" -- NthDay nil result
local tCon = table.concat
-- 00) Блок многократно используемых списков
local bool_to_number={ [true]=1, [false]=0 }
local monthlang = {"января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"}
local month_to_num = {["января"]=1,["февраля"]=2,["марта"]=3,["апреля"]=4,["мая"]=5,["июня"]=6,
["июля"]=7,["августа"]=8,["сентября"]=9,["октября"]=10,["ноября"]=11,["декабря"]=12,["-"]=""}
local monthd = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
local params = { {"г", "g"}, {"ю", "j"}}
local comment = { '<span style="border-bottom: 1px dotted; cursor: help" title="по юлианскому календарю">','</span>'}
-- duplicates:
-- AST, BST, CST, ECT, IST, MST, PST, SST,
local known_tzs = {
ACDT='+10:30', ACST='+09:30', ACT ='+08:00', ADT ='-03:00', AEDT ='+11:00',
AEST='+10:00', AFT ='+04:30', AKDT='-08:00', AKST ='-09:00', AMST ='+05:00',
AMT ='+04:00', ART ='-03:00', AST ='+03:00', AST ='+04:00', AST ='+03:00',
AST ='-04:00', AWDT='+09:00', AWST='+08:00', AZOST='-01:00', AZT ='+04:00',
BDT ='+08:00', BIOT='+06:00', BIT ='-12:00', BOT ='-04:00', BRT ='-03:00',
BST ='+06:00', BST ='+01:00', BTT ='+06:00', CAT ='+02:00', CCT ='+06:30',
CDT ='-05:00', CEDT='+02:00', CEST='+02:00', CET ='+01:00', CHAST='+12:45',
CIST='-08:00', CKT ='-10:00', CLST='-03:00', CLT ='-04:00', COST ='-04:00',
COT ='-05:00', CST ='-06:00', CST ='+08:00', CVT ='-01:00', CXT ='+07:00',
CHST='+10:00', DFT ='+01:00', EAST='-06:00', EAT ='+03:00', ECT ='-04:00',
ECT ='-05:00', EDT ='-04:00', EEDT='+03:00', EEST ='+03:00', EET ='+02:00',
EST ='-05:00', FJT ='+12:00', FKST='-03:00', FKT ='-04:00', GALT ='-06:00',
GET ='+04:00', GFT ='-03:00', GILT='+12:00', GIT ='-09:00', GMT ='+00:00',
GST ='-02:00', GYT ='-04:00', HADT='-09:00', HAST ='-10:00', HKT ='+08:00',
HMT ='+05:00', HST ='-10:00', IRKT='+08:00', IRST ='+03:30', IST ='+05:30',
IST ='+01:00', IST ='+02:00', JST ='+09:00', KRAT ='+07:00', KST ='+09:00',
LHST='+10:30', LINT='+14:00', MAGT='+11:00', MDT ='-06:00', MIT ='-09:30',
MSD ='+04:00', MSK ='+03:00', MST ='+08:00', MST ='-07:00', MST ='+06:30',
MUT ='+04:00', NDT ='-02:30', NFT ='+11:30', NPT ='+05:45', NST ='-03:30',
NT ='-03:30', OMST='+06:00', PDT ='-07:00', PETT ='+12:00', PHOT ='+13:00',
PKT ='+05:00', PST ='-08:00', PST ='+08:00', RET ='+04:00', SAMT ='+04:00',
SAST='+02:00', SBT ='+11:00', SCT ='+04:00', SLT ='+05:30', SST ='-11:00',
SST ='+08:00', TAHT='-10:00', THA ='+07:00', UTC ='+00:00', UYST ='-02:00',
UYT ='-03:00', VET ='-04:30', VLAT='+10:00', WAT ='+01:00', WEDT ='+01:00',
WEST='+01:00', WET ='+00:00', YAKT='+09:00', YEKT ='+05:00',
-- US Millitary (for RFC-822)
Z='+00:00', A='-01:00', M='-12:00', N='+01:00', Y='+12:00',
}
local category = {
["no_parameters"]=
"<!--[[Категория:Модуль:Calendar:Страницы без параметров]]-->",
["incomplete_parameters"]=
"<!--[[Категория:Модуль:Calendar:Страницы с неполными или некорректными параметрами]]-->",
["without_verification"]=
"<!--[[Категория:Модуль:Calendar:Страницы без проверки параметров]]-->",
["erroneous_parameters"]=
"<!--[[Категория:Модуль:Calendar:Страницы с ошибочными параметрами]]-->"
}
-- несколько параметров передаются вместе с кодом ошибки в таблице, один может быть передан простым значением
local e = {
["start"]="<span class=error>Ошибка: ",
["ending"]=".</span>",
["no_pattern_match"]="строка «%s» не совпадает с заданными паттернами",
["no_valid_date"]="дата «%s» не является корректной",
["wrong_jd"]="юлианская дата %s вне диапазона",
["no_data"]="нет входящих данных",
["too_many_arguments"]="ожидается менее %i аргументов",
["too_little_arguments"]="ожидается более %i аргументов",
["wrong_calculation"]="даты %s и %s не прошли проверку, %s дней разница",
["unknown_param"]="параметр %s неизвестен",
["unknown_error"]="неизвестная ошибка",
["tech_error"]="ошибка в функции %s",
["box_date"]="строка «%s» не является верной датой, пожалуйста, укажите дату в формате ГГГГ-ММ-ДД"
-- [""]="",
}
local tzs_names = {"ACDT","ACST","ACT","ADT","AEDT","AEST","AFT","AKDT","AKST",
"AMST","AMT","ART","AST","AST","AST","AST","AWDT","AWST","AZOST","AZT","BDT",
"BIOT","BIT","BOT","BRT","BST","BST","BTT","CAT","CCT","CDT","CEDT","CEST",
"CET","CHAST","CIST","CKT","CLST","CLT","COST","COT","CST","CST","CVT","CXT",
"CHST","DFT","EAST","EAT","ECT","ECT","EDT","EEDT","EEST","EET","EST","FJT",
"FKST","FKT","GALT","GET","GFT","GILT","GIT","GMT","GST","GYT","HADT","HAST",
"HKT","HMT","HST","IRKT","IRST","IST","IST","IST","JST","KRAT","KST","LHST",
"LINT","MAGT","MDT","MIT","MSD","MSK","MST","MST","MST","MUT","NDT","NFT",
"NPT","NST","NT","OMST","PDT","PETT","PHOT","PKT","PST","PST","RET","SAMT",
"SAST","SBT","SCT","SLT","SST","SST","TAHT","THA","UTC","UYST","UYT","VET",
"VLAT","WAT","WEDT","WEST","WET","YAKT","YEKT","Z","A","M","N","Y","MSK"}
local pattern = { -- для распознавания дат, переданных одним строчным параметром
{"(-?%d%d%d%d?)[-%.%s/\\](%d%d)[-%.%s/\\](%d%d)", ["order"] = {3,2,1} }, -- yyyy mm dd
{"(%d+)[-%.%s/\\](%d+)[-%.%s/\\](%d%d%d%d?)", ["order"] = {1,2,3} }, -- dd mm yyyy
{"(%d%d)[-%.%s/\\](%d%d%d%d?)", ["order"] = {2,3} }, -- mm yyyy
{"(%d%d%d%d?)[-%.%s/\\](%d%d)", ["order"] = {3,2} }, -- yyyy mm
{"(%d+)%s(%l+)%s(%d%d%d%d?)", ["order"] = {1,2,3} }, -- d mmm y
{"(%l+)%s(%d+),?%s(%d%d%d%d?)", ["order"] = {2,1,3} }, -- mmm d, y
{"(%l+)%s(%d%d%d%d?)", ["order"] = {2,3} }, -- mmm y
}
local time_units = {"year","month","day"} --не используется
--[[ local time_units = {"second", "minute", "hour",
"day_of_month", "day_of_week", "day_of_year",
"week", "month", "year", "year_of_century", "century"} ]]--
-- напоминание чтобы сделать более точные пересчёты - с часами / расчёт длительностей периодов
local mnlang = {"ru_G", "ru_N", "en", "en_S", "de", "fr"}
local month_lang = {
["ru_G"] = {"января","февраля","марта","апреля","мая","июня",
"июля","августа","сентября","октября","ноября","декабря"},
["ru_N"] = {"январь","февраль","март","апрель","май","июнь",
"июль","август","сентябрь","октябрь","ноябрь","декабрь"},
["en"] = {"january", "february", "march", "april", "may", "june",
"july", "august", "september", "october", "november", "december"},
["en_S"] = {"jan", "feb", "mar", "apr", "may", "jun",
"jul", "aug", "sep", "oct", "nov", "dec"},
["de"] = {"januar", "februar", "märz", "april", "mai", "juni",
"juli", "august", "september", "oktober", "november", "dezember"},
["fr"] = {"janvier", "février", "mars", "avril", "mai", "juin",
"juillet", "août", "septembre", "octobre", "novembre", "décembre"}
}
-- заполняется автоматически
local reverse_month_lang = {}
-- вспомогательная функция для обращения таблиц (смена ключей со значениями)
local reverse_table = function (strait_table)
local reversed_table = {}
for k,v in pairs(strait_table) do
reversed_table[v] = k
end
return reversed_table
end
-- запуск цикла по заполнению обратных таблиц, необходимых для распознавания дат
local filling_months = function (mnlang, month_lang)
for i=1, #mnlang do
reverse_month_lang[mnlang[i]] = reverse_table(month_lang[mnlang[i]])
end
end
-- 10) Блок общих функций
local function trim(str)
if not str then return nil
else return str:match'^()%s*$' and '' or str:match'^%s*(.*%S)'
end
end
local function purif(str)
if str == "" or str == nil then
return nil
elseif type(tonumber(str)) == "number" then
return math.floor(tonumber(str))
else
return nil
end
-- need .5 -- ,5 number format converter?
end
local function is(str)
if (not str) or (str == "") then return false
else return yesno(str,false)
end
end
local function init(num)
local output = {}
for i=1,num do
table.insert(output, {["year"]="", ["month"]="", ["day"]=""})
end
return unpack(output)
end
local function isyear(tbl)
if type(tbl) ~= 'table' then return false
elseif not tbl["year"] then return false
elseif type(tbl["year"]) == 'number' then return true
else return false
end
end
local function inbord(val, down, up)
return not (type(up) ~= "number" or type(down) ~= "number" or type(val) ~= "number" or up < down or val < down or val > up)
end
local function shallowcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in pairs(orig) do
copy[orig_key] = orig_value
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
local inlist = function ( var, list )
local n = #list
local inlist = false
for i=1,n do
if var == list[i] then inlist = true end
end
return inlist
end
-- 20) Блок общих проверочных функций, связанных с датами
local function unwarp(tbl)
if not tbl then return ""
elseif type(tbl) ~= "table" then return tbl
elseif (tbl.day or tbl.month or tbl.year) then
return (tbl.year or "?").."-"..(tbl.month or "?").."-"..(tbl.day or "?")
else return (tbl[3] or "?").."-"..(tbl[2] or "?").."-"..(tbl[1] or "?")
end
end
local function leap_year(y,jul)
if (not y) or (type(y) ~= "number")
then return false
elseif (y % 4) ~= 0
then return false
elseif not jul and (y % 100 == 0 and y % 400 ~= 0)
then return false
else return true
end
end
-- функция для вычисления последнего дня месяца для юлианского и григорианского календарей
local function month_end_day (month,year,is_julian)
local month_end_day = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} -- если не задан год, дата 29 февраля считается допустимой
if not month or type(month) ~= "number" or month < 1 or month > 12 then return nil
elseif month ~= 2 or not year then return month_end_day[month]
elseif month == 2 and (year % 4) == 0 and not ((not is_julian) and (year % 100 == 0 and year % 400 ~= 0)) then return 29
elseif month == 2 then return 28
else return nil -- в случае не целого значения входящих параметров или при иных непредусмотренных событиях
end
end
local function isdate ( chain , jul ) -- можно использовать для проверки таблиц с полями day, month, year
if not chain then return false
elseif (not type(chain) == "table")
or (not inbord(chain.year,-9999,9999))
or (not inbord(chain.month,1,12))
or (not inbord(chain.day,1,31))
or chain.day > monthd[chain.month]
-- or chain.year == 0
then return false
elseif chain.month == 2 and chain.day == 29 and not leap_year(chain.year,jul)
then return false
else return true end
-- check for other calendars needed?
end
local function ispartdate ( chain )
if not chain then return false
elseif not (type(chain) == "table") then return false
elseif (inbord(chain.year,-9999,9999)
or inbord(chain.month,1,12)
or inbord(chain.day,1,31)) then return true
else return false
end
-- partial date
-- more detailed check for 31.02.0000 needed
-- check for other calendars needed
end
-- from date1 to date2 in one year (beetwen jan-dec, dec-jan needed)
local function partdist(date1,date2)
local mont, dist = 0, 0
local d1d, d1m, d2d, d2m = (date1["day"] or ""), (date1["month"] or ""),(date2["day"] or ""), (date2["month"] or "")
if not (inbord(d1d,1,31) and inbord(d2d,1,31)) then return false end
-- нужна доп. проверка частичных дат на корректность
if (inbord(d1m,1,12) or inbord(d2m,1,12))
and (d1m == "" or d2m == "") then
mont = purif(date1["month"] or date2["month"])
d1m, d2m = mont, mont
end
-- mw.log("📏 day: " ..d1d .."->"..d2d.." month: ".. d1m.."->"..d2m )
if (inbord(d1m,1,12) and d1d <= monthd[d1m])
and (inbord(d2m,1,12) and d2d <= monthd[d2m]) then
if d2m == d1m
then dist = d2d - d1d
else dist = monthd[d1m] - d1d + d2d
end
return dist
else return math.huge
end
end
local function dmdist(d1,d2)
local p1,p2 = math.huge,math.huge
if not not partdist(d1,d2) then
p1=partdist(d1,d2)
end
if not not partdist(d2,d1) then
p1=partdist(d2,d1)
end
-- if (not p1) or (not p2) then
-- return (p1 or "") .. (p2 or "")
-- else
-- mw.log("d1, d2 = " .. undate(d1) .. ", " .. undate(d2))
return math.min(tonumber(partdist(d1,d2)) or math.huge,tonumber(partdist(d2,d1)) or math.huge)
-- end
end
-- 30) Блок функций для обработки ввода-вывода дат
local function undate(tbl)
if not tbl then return ""
else return (tbl.year or "").."-"..(tbl.month or "").."-"..(tbl.day or "")
end
end
-- функция для нормализации значений дат и перевода месяцев в числа
local function numerize(str)
if type(str) == "number" then
return math.floor(str)
elseif str == "" or str == nil or type(str) ~= "string" then
return nil
elseif type(tonumber(str)) == "number" then
return math.floor(tonumber(str))
else
for i=1, #mnlang do
if inlist(mw.ustring.lower(str),month_lang[mnlang[i]]) then
return reverse_month_lang[mnlang[i]][mw.ustring.lower(str)]
end
end
end
end
-- функция распознавания даты, переданной одной строкой
local function parse_date(date_string)
if type(date_string) ~= "string" or date_string == "" then return nil end
local out_date_str = {"","",""}
local error_data = {}
for i=1, #pattern do
local result_1, result_2, result_3 = mw.ustring.match(mw.ustring.lower(date_string),pattern[i][1])
if (result_1 or "") > "" then
out_date_str[pattern[i].order[1]] = result_1
out_date_str[pattern[i].order[2]] = result_2
if (pattern[i].order[3]) then out_date_str[pattern[i].order[3]] = result_3 end
-- mw.log("Паттерн " .. i .. ", строка: " .. date_string)
break
end
end
local date = {
["day"] =numerize(out_date_str[1]),
["month"]=numerize(out_date_str[2]),
["year"] =numerize(out_date_str[3])}
return date --, error_data
end
----[[ УСТАРЕЛО ]]----
local numstr2date = function(numstr)
local format = "Y-m-d"
local iso_date = mwlang:formatDate(format,numstr)
local y,m,d = string.match(iso_date, "(%d+)-(%d+)-(%d+)")
local dateout = {["year"]=purif(y), ["month"]=purif(m), ["day"]=purif(d)}
return dateout
end
--local numstr2date = function(numstr)
-- local nums = {}
-- local dateout = {}
-- for num in string.gmatch(numstr,"(%d+)") do
-- table.insert(nums,purif(num))
-- end
-- if #nums ~= 3 then error("В поле даты вместо трёх чисел с разделителями указано " .. #nums)
-- elseif not inbord(nums[2],1,12) then error("Месяц с номером " .. nums[2] .. " не найден")
-- elseif not inbord(nums[3],1,31) then
-- dateout = {["year"]=nums[3], ["month"]=nums[2], ["day"]=nums[1]}
-- elseif not inbord(nums[1],1,31) then
-- dateout = {["year"]=nums[1], ["month"]=nums[2], ["day"]=nums[3]}
-- elseif inbord(nums[1],1,31) then
-- dateout = {["year"]=nums[3], ["month"]=nums[2], ["day"]=nums[1]}
-- else
-- local mwlang = mw.getContentLanguage()
-- implement mwlang:formatDate(format,datein,true) here
-- return error("Не распознано " .. numstr .. " как дата")
-- end
-- return dateout
--end
local function year2lang(numyear,yearmark,wiki)
if not numyear then return "" end
if not yearmark then yearmark = "" end
local output = ""
local bcmark = " до н. э."
if numyear > 0 then bcmark = ""
else numyear = 1 - numyear end
if wiki then
-- output = tCon({'[[', numyear,' год',bcmark,'|', numyear,']]', " ", yearmark, " ", bcmark})
output = tCon({'[[', numyear,' год',bcmark,'|', trim(numyear .. " " .. yearmark .. " " .. bcmark), ']]'})
else
output = tCon({numyear, " ", yearmark, bcmark})
end
return trim(output)
end
local function day2lang(datein,wikidate,wiki,inner_brt)
-- if not isdate(wikidate) then wiki = false end
if not ispartdate(datein) then return "" end
local dm_separ, output = "", nil
if (not (not datein.day)) and (not (not datein.month)) then dm_separ = " " end
if (not datein.month) then datein.month = "" end
if (not datein.day) then datein.day = "" end
local monlan = monthlang[datein.month] or ""
if wiki and not inner_brt then
output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "",
"|", (datein.day or ""), dm_separ, monlan, "]]"})
elseif wiki then
output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "",
"|", (datein.day or ""), dm_separ, monlan})
else
output = tCon({datein.day, dm_separ, monlan})
end
return trim(output)
end
local function triple_txt2date(d,m,y)
-- добавить (args[1]:match("(%a+)") or "-") для нестандартной записи
-- mw.ustring.match((m or ""),"(%a+)")
local msg = ""
local year = purif((y or "-"):match("(%d+)"))
local month = purif(month_to_num[string.lower(mw.ustring.match((m or ""),"(%a+)"))])
local day = purif((d or "-"):match("(%d+)"))
if not month then
msg = category.incomplete_parameters
month = purif(month_to_num[string.lower(mw.ustring.match((d or ""),"(%a+)") or "-")])
end
if (not day) and ((purif(string.match(m or "","(%d+)") or "") or 32) <= (monthd[month] or 31)) then
msg = category.incomplete_parameters
day = purif(m:match("(%d+)") or "")
end
if not year then
msg = category.incomplete_parameters
year = purif(string.match(m or "","(%d+)") or "")
end
local dateout = {["year"]=year, ["month"]=month, ["day"]=day, ["msg"]=msg}
return dateout
end
local function glue(d1,m1,y1,d2,m2,y2)
if (not d1) and (not m1) and (not y1) and (not d2) and (not m2) and (not y2) then
return category.incomplete_parameters end
local gd,gm,gy,jd,jm,jy =
(d1 or ""),
(m1 or ""),
(y1 or ""),
(d2 or ""),
(m2 or ""),
(y2 or "")
--mw.log(tCon({gd,gm,gy,jd,jm,jy}))
local gm_sep = {" [["," год|","]]"}
if (not gy) or (gy == "") then gm_sep = {"","",""} end
return tCon({comment[1],trim(trim(jd .. " " .. jm) .. " " .. jy ),
comment[2]," ([[",trim(gd .. " " .. gm),"]]",gm_sep[1],(gy:match("(%d+)") or ""),
gm_sep[2],gy,gm_sep[3],")",category.incomplete_parameters})
end
-- добавить отображение без года
local function double_couple(jdate, gdate, wd, wm, wy, sq_brts, yearmark)
local msg = ""
msg = (jdate.msg or "") .. (gdate.msg or "")
local cd = {}
local jd = shallowcopy(jdate)
local gd = shallowcopy(gdate)
local left = "("
local right = ")"
if sq_brts then
left = "["
right = "]"
end
if (not isdate(jdate,true)) then return error((jdate.day or "") .. "." .. (jdate.month or "") .."." .. (jdate.year or "") .. " неподходящая дата")
elseif (not isdate(gdate)) then return error((gdate.day or "") .. "." .. (gdate.month or "") .."." .. (gdate.year or "") .. " неподходящая дата") end
if jd.year == gd.year then
cd.year = gd.year
gd.year, jd.year = nil, nil
end
if jd.month == gd.month then
cd.month = gd.month
gd.month, jd.month = nil, nil
end
if (not not cd.month) and wm then
return tCon({comment[1] .. trim(day2lang(jd,jdate,false) .. " " .. year2lang(jd.year,yearmark,false)) .. comment[2],
trim(left .. day2lang(gd,gdate,wd,wm) .. " " .. year2lang(gd.year,yearmark,wy)) .. right,
day2lang(cd,gdate,false) .. "]]", trim(year2lang(cd.year,yearmark,wy)..msg)}, " ")
end
return tCon({comment[1] .. trim(day2lang(jd,jdate,false) .. " " .. year2lang(jd.year,yearmark,false)) .. comment[2],
trim(left .. day2lang(gd,gdate,wd) .. " " .. year2lang(gd.year,yearmark,wy)) .. right,
trim(day2lang(cd,gdate,false)), trim(year2lang(cd.year,yearmark,wy)..msg)}, " ")
end
-- 40) Блок функций для перевода дат с использованием [[Юлианская дата]]
local function gri2jd( datein )
if not isdate(datein) then return error((datein.day or "") .. "." .. (datein.month or "") .."." .. (datein.year or "") .. " неподходящая дата") end
local year = datein.year
local month = datein.month
local day = datein.day
-- jd calculation
local a = math.floor((14 - month)/12)
local y = year + 4800 - a
local m = month + 12*a - 3
local offset = math.floor(y/4) - math.floor(y/100) + math.floor(y/400) - 32045
local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
-- jd validation
local low, high = -1931076.5, 5373557.49999
if not (low <= jd and jd <= high) then
return error((datein.day or "") .. "." .. (datein.month or "") .. "." .. (datein.year or "") .. " выходит за пределы разрешённого диапазона")
end
return jd
end
local function jd2jul( jd )
if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end
-- calendar date calculation
local c = jd + 32082
local d = math.floor((4*c + 3)/1461)
local e = c - math.floor(1461*d/4)
local m = math.floor((5*e + 2)/153)
local year_out = d - 4800 + math.floor(m/10)
local month_out = m + 3 - 12*math.floor(m/10)
local day_out = e - math.floor((153*m + 2)/5) + 1
-- output
local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
return dateout
end
local function jul2jd( datein )
if not isdate(datein,true) then return error((datein.day or "") .. "." .. (datein.month or "") ..".".. (datein.year or "") .. " неподходящая дата") end
local year = datein.year
local month = datein.month
local day = datein.day
-- jd calculation
local a = math.floor((14 - month)/12)
local y = year + 4800 - a
local m = month + 12*a - 3
local offset = math.floor(y/4) - 32083
local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
-- jd validation
local low, high = -1930999.5, 5373484.49999
if not (low <= jd and jd <= high) then
return error((datein.day or "") .. "." .. (datein.month or "") .."." .. (datein.year or "") .. " выходит за пределы разрешённого диапазона")
end
return jd
end
local function jd2gri( jd )
if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end
-- calendar date calculation
local a = jd + 32044
local b = math.floor((4*a + 3) / 146097)
local c = a - math.floor(146097*b/4)
local d = math.floor((4*c+3)/1461)
local e = c - math.floor(1461*d/4)
local m = math.floor((5*e+2)/153)
local day_out = e - math.floor((153*m+2)/5)+1
local month_out = m + 3 - 12*math.floor(m/10)
local year_out = 100*b + d - 4800 + math.floor(m/10)
-- output
local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
return dateout
end
local function astroyear(num, bc)
if not num then return error()
elseif type(num) ~= "number" then return error()
end
if num < 1 then return num end
if not bc then return num
else return 1 - num
end
end
local function recalc(datein,calend)
if inlist(calend,params[1]) then
return jd2jul(gri2jd(datein)), datein
elseif inlist(calend,params[2]) then
return datein, jd2gri(jul2jd(datein))
else error("Параметр " .. (calend or "") .. " не опознан, разрешённые: " .. tCon(params[1]," ") .. " и " .. tCon(params[2]," "))
end
end
-- 50) Функции для обработки UTC
local function utc(str,margin)
local d = 1
local dchar = "+"
local beginning = "[[UTC"
local ending = "]]"
local cat = ""
local nums = {}
local hmarg, timedec = 0, 0
local mmarg = "00"
local output = ""
-- checking type of input
if not margin then margin = 0
elseif type(tonumber(margin)) ~= 'number' then
output = "Can't shift by " .. margin
error(output)
end
if type(str) ~= 'string' then
error("Нет входящей строки")
elseif str:byte(1) == 43 then
elseif inbord(str:byte(1),48,57) then cat = "[[Категория:Википедия:Ошибка в часовом поясе НП]]"
elseif str:byte(1) == 45 or string.sub(str,1,3) == "−" or string.sub(str,1,1)=="-" then d = -1
else
error(string.char(str:byte(1)) .. " недопустимый первый символ")
end
-- parsing input
for num in string.gmatch(str,"(%d+)") do
table.insert(nums,purif(num))
end
if #nums > 2 then error("Ожидается всего 2 числа, а не " .. #nums)
elseif #nums == 0 then error("Необходимо что-то ввести")
elseif #nums == 1 then
if inbord(nums[1],0,14) then timedec = d*nums[1] + margin
else error("Только часы от -14 до 14") end
elseif #nums == 2 then
if not inbord(nums[1],0,14) then error("Только часы от -14 до 14")
elseif not inbord(nums[2],0,59) then error("Минуты только от 0 до 59")
else
timedec = d*(nums[1] + nums[2]/60) + margin
end
end
if tonumber(timedec) == purif(timedec) then hmarg = timedec
else
local h, m = math.modf(math.abs(timedec))
hmarg = h
mmarg = math.floor(m*60)
end
if timedec == 0 then
dchar = "±"
elseif timedec > 0 then
elseif timedec < 0 then
dchar = "−"
end
-- output
output = beginning .. dchar .. math.abs(hmarg) .. ":" .. string.format("%02d",mmarg) .. ending .. cat
return output
end
-- 60) Блок функций ввода-вывода
function p.NthDay( frame )
local args = getArgs(frame, { frameOnly = true })
local num, wday, mont, yea, format =
purif(args[1]), purif(args[2]), purif(args[3]), purif(args[4]), args[5]
if not format then format = "%d.%m.%y" end
if not inbord(num,-5,5) then
return error("The number must be between -5 and 5")
elseif num == 0 then
return error("The number must not be zero") end
if not inbord(wday,0,6) then
return error("The day of the week must be between 0 and 6") end
if not inbord(mont,1,12) then
return error("The month must be between 1 and 12") end
if not inbord(yea,0,9999) then
return error("Wrong year number") end
if inbord(num,1,5) then
local m_start = os.time{year=yea, month=mont, day=1, hour=0}
local m_wds = tonumber(os.date("%w", m_start))
local start_shift = (
(num - bool_to_number[wday >= m_wds]) * 7
- (m_wds - wday)
) * 24 * 60 * 60
local tim = m_start + start_shift
if tonumber(os.date("%m", tim)) == mont then
return (os.date(format, tim))
else
return (err)
end
elseif inbord(num,-5,-1) then
local m_end = os.time{year = yea, month = mont + 1, day = 1, hour = 0} - 24 * 60 * 60
local m_wde = tonumber(os.date("%w", m_end))
local end_shift = ((math.abs(num + 1) + bool_to_number[wday > m_wde]) * 7
+ (m_wde - wday)) * 24 * 60 * 60
local tim = m_end - end_shift
if tonumber(os.date("%m", tim)) == mont then
return (os.date(format, tim))
else
return (err)
end
end
end
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}})
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"1.2.1602"}})
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12.12.2021"}})
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"2021.12.12"}})
function p.ToIso( frame )
local args = getArgs(frame, { frameOnly = true })
local datein = args[1]
-- инициализация, заполнение обратных таблиц, копирование параметров
filling_months(mnlang, month_lang)
-- парсинг входящей даты по шаблону
local date = parse_date(datein)
if not (type(date.year) == 'number') then
return ("Wrong year: " .. unwarp(date))
end
if not (1 <= date.month and date.month <= 12) then
return ("Wrong month: " .. unwarp(date))
end
if not date.day or not (1 <= date.day and date.day <= month_end_day(date.month,date.year)) then
return ("Wrong day: " .. unwarp(date))
end
local timedate = os.time{year=date.year, month=date.month, day=date.day}
local date = os.date("%Y-%m-%d", timedate)
return date
end
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"1.2.1602"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"декабрь 2020"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12-2020"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12.12.2021"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"2021.12.12"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"2021.11"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"11.2021"}})
function p.BoxDate( frame )
local args = getArgs(frame, { frameOnly = true })
local txtDateIn, strFormat = args[1], args[2]
local txtDateOut, date, status = p.bxDate(txtDateIn, strFormat, params)
if status.brk then
return error(status.errorText)
else
return txtDateOut
end
end
function p.bxDate( txtDateIn , strFormat, params ) -- к отладке
local txtDateOut, date, status = "", {}, {brk = false, errorCat = "", errorText = ""}
strFormat = strFormat or "j xg Y"
-- заглушка - таблица параметров на будущее
params = params or {}
if not txtDateIn then
status.errorText = e.no_data
status.errorCat = category.no_parameters
status.brk = true
else
-- заполнение служебных таблиц
filling_months(mnlang, month_lang)
end
if not status.brk then
-- парсинг входящей даты по шаблону
date = parse_date(txtDateIn)
-- заменить сообщения об ошибках на списочные
if not (date.year and type(date.year) == 'number') then
status.errorText = string.format(e.box_date,txtDateIn)
status.errorCat = category.incomplete_parameters
status.brk = true
end
if not inbord(date.month,1,12) then
status.errorText = string.format(e.box_date,txtDateIn)
status.errorCat = category.incomplete_parameters
status.brk = true
end
if not date.day and string.find(strFormat,"[dDjlNwzW]") then
strFormat = trim(string.gsub(string.gsub(strFormat,"xg","F"),"[dDjlNwzW]",""))
elseif not date.day then
elseif not inbord(date.day,1,month_end_day(date.month,date.year)) then
status.errorText = string.format(e.box_date,txtDateIn)
status.errorCat = category.incomplete_parameters
status.brk = true
end
end
if not status.brk then
txtDateOut = mwlang:formatDate(strFormat,tCon({date.year,date.month,date.day},"-"),true)
end
return txtDateOut, date, status
end
function p.ToDate( frame ) -- возможно неиспользуемая
local args = getArgs(frame, { frameOnly = true })
local mwlang = mw.getContentLanguage()
local datein = args[1]
local format = "j xg Y"
if not string.match(datein, "%p") then return datein
elseif not args[2] then
else format = args[2]
end
return mwlang:formatDate(format,datein,true)
end
-- =p.unitime(mw.getCurrentFrame():newChild{title="smth",args={"−1:30","1"}})
function p.unitime( frame )
local args = getArgs(frame, { frameOnly = true })
local DST = 0
if not args[2] then
else DST = 1 end
local utcin = ""
local input = args[1]
if not input then return "" end
if inlist(input:upper(),tzs_names) then
utcin = known_tzs[input:upper()]
elseif (string.sub(input:upper(),1,3) == 'UTC') and (string.len(input) < 10) then
utcin = string.sub(input,4)
else
if string.sub(input,1,1) == '['
or string.sub(input,1,1) == '{'
or string.sub(input,1,1):upper() == 'U'
or string.sub(input,1,1):upper() == 'M' then
return input
-- elseif not string.find(string.upper(string.sub(input,1,1)),"[\65-\90]") or
-- not string.find(string.upper(string.sub(input,1,1)),"[\192-\223]") then
-- return input
else utcin = input end
end
-- elseif string.sub(input,1,3) ~= "−" then utcin = input
-- or not (not input:find("[А-я]")) при наличии в строке юникода не работает
local output = ""
if DST == 0 then output = utc(utcin)
else output = utc(utcin) .. ", [[летнее время|летом]] " .. utc(utcin,DST)
end
return output
end
-- УСТАРЕЛО
-- =p.OldDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020","ю",["bc"]="1",["wd"]="1",["wy"]="1",["sq_brts"]="1",["yearmark"]="г."}})
function p.OldDate( frame )
local args = getArgs(frame, { frameOnly = true })
if not args[1] then return err end
local gdate, jdate = {}, {}
local strin = args[1]
local cal = args[2]:lower() or "г"
local bc = is(args["bc"])
local wd = is(args["wd"])
local wm = is(args["wm"])
local wy = is(args["wy"])
if not wd then wm = false end
local sq_brts = is(args["sq_brts"])
local yearmark = "года"
if yesno(args["yearmark"]) then
elseif yesno(args["yearmark"]) == false then yearmark = ""
else yearmark = trim(args["yearmark"]) or "года" end
-- local infocard = is(args["infocard"])
-- local catName = args["catName"] or false
local datein = numstr2date(strin)
datein.year = astroyear(datein.year, bc)
jdate, gdate = recalc(datein,cal)
return double_couple(jdate, gdate, wd, wm, wy, sq_brts, yearmark)
end
-- =p.NewDate(mw.getCurrentFrame():newChild{title="Salt",args={"2020-02-20"}})
-- =p.NewDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020","ю",["bc"]="1",["wd"]="1",["wy"]="1",["sq_brts"]="1",["yearmark"]="г."}})
-- =p.NewDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020",["bc"]="0",["wd"]="1",["wy"]="1",["sq_brts"]="0",["yearmark"]=""}})
function p.NewDate( frame )
local args = getArgs(frame, { frameOnly = true })
if not args[1] then return err end
local strin = args[1]
local year, month, day
if not not strin:match( "(-?%d%d%d%d%d)-(%d%d)-(%d%d)" ) then
year, month, day = strin:match( "(-?%d%d%d%d%d)-(%d%d)-(%d%d)" )
elseif not not strin:match( "(-?%d+)-(%d+)-(%d+)" ) then
year, month, day = strin:match( "(-?%d+)-(%d+)-(%d+)" )
elseif not not strin:match( "(%d%d)%.(%d%d)%.(-?%d%d%d%d%d)" ) then
day, month, year = strin:match( "(%d%d)%.(%d%d)%.(-?%d%d%d%d%d)" )
elseif not not strin:match( "(%d+)%.(%d+)%.(-?%d+)" ) then
day, month, year = strin:match( "(%d+)%.(%d+)%.(-?%d+)" )
end
if not year then return error(args[1] .. " не подходит под форматы yyyy-mm-dd или dd.mm.yyyy")
end
local cal = "г"
if (not args[2]) or (args[2] == "") then cal = "г"
else cal = args[2]:lower() end
local bc,wd,wm,wy,sq_brts =
is(args["bc"]),
is(args["wd"]),
is(args["wd"]) and is(args["wm"]),
is(args["wy"]),
is(args["sq_brts"])
year = astroyear(purif(year),bc)
local datein = {["year"]=purif(year), ["month"]=purif(month), ["day"]=purif(day)}
local jdate, gdate = recalc(datein,cal)
local yearmark = "года"
local ym = args["yearmark"] or ""
if yesno(ym) then
elseif yesno(ym) == false then yearmark = ""
else
if not not ym:match("(%d+)") then
error("Цифры в обозначении года: " .. ym)
else yearmark = trim(ym) or "года" end
end
return double_couple(jdate, gdate, wd, wm, wy, sq_brts, yearmark)
end
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"3","июня",nil,"21","мая"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"28 августа","","1916 года","15"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"3","июня","1900","21","мая"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"6","июня","1889 год","25","мая"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"28","ноября","1917","15"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"28 августа","nil","1916 года","15"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"4","января","1915","22","декабря","1914 года"}})
-- {{OldStyleDate|день (НС)|месяц (НС)|год (НС)|день (СС)|месяц (СС)|год (СС)}}
function p.Test( frame )
local args = getArgs(frame, { frameOnly = true })
-- необходима проверка и замена nil на " "
--[[mw.log((args[1] or "") .. " " ..
(args[2] or "") .. " " ..
(args[3] or "") .. " " ..
(args[4] or "") .. " " ..
(args[5] or "") .. " " ..
(args[6] or "")) ]]--
local ingdate = triple_txt2date(args[1],args[2],args[3])
local injdate = triple_txt2date(args[4],args[5],args[6])
local j1date, g1date, j2date, g2date = init(4)
mw.log("ingdate-".. (undate(ingdate) or ""))
mw.log("injdate-".. (undate(injdate) or ""))
local bc,wd,wm,wy,sq_brts,ny =
is(args["bc"]),
is(args["wd"]),
is(args["wd"]) and is(args["wm"]),
is(args["wy"]),
is(args["sq_brts"]),
is(args["ny"])
-- подавление формата для локальных тестов
local wd, wm, wy = true, true, true
local yearmark = "года"
local ym = args["yearmark"] or ((mw.ustring.match((args[3] or ""),"(%a+)") or mw.ustring.match((args[6] or ""),"(%a+)")) or "")
-- mw.log("ym " .. ym)
if yesno(ym) then
elseif yesno(ym) == false then yearmark = ""
else
if not not ym:match("(%d+)") then
error("Цифры в обозначении года: " .. ym)
else yearmark = trim(ym) or "года" end
end
if isdate(ingdate) or isdate(injdate) then
if isdate(ingdate) then
j1date, g1date = recalc(ingdate,"g")
ingdate["full"] = true
end
if isdate(injdate) then
j2date, g2date = recalc(injdate,"j")
injdate["full"] = true
end
if ispartdate(ingdate) and ispartdate(injdate) then
mw.log("📏 " .. dmdist(ingdate,injdate))
mw.log("📏 " .. dmdist(j1date,g1date))
mw.log("📏 " .. dmdist(j2date,g2date))
mw.log("📏 " .. dmdist(ingdate,g1date))
mw.log("📏 " .. dmdist(injdate,j2date))
end
end
if ny then
if isyear(j1date) then
else j1date["year"] = "" end
if isyear(j2date) == nil then
else j2date["year"] = "" end
if isyear(g1date) == nil then
else g1date["year"] = "" end
if isyear(g2date) == nil then
else g2date["year"] = "" end
end
if (isdate(j1date) and isdate(g1date) and isdate(j2date) and isdate(g2date)) then
if ((j1date.year == j2date.year)
and (j1date.month == j2date.month)
and (j1date.day == j2date.day)) then
return double_couple(j1date, g1date, wd, wm, wy, sq_brts, yearmark)
else
mw.log("📏 " .. (tostring(dmdist(ingdate,injdate)) or ""))
return glue(args[1],args[2],args[3],args[4],args[5],args[6])
-- категория (предположительная разница в днях) и частичный вывод
end
elseif isdate(j1date) and isdate(g1date) then
return double_couple(j1date, g1date, wd, wm, wy, sq_brts, yearmark) -- категория плюс частичная проверка
elseif isdate(j2date) and isdate(g2date) then
return double_couple(j2date, g2date, wd, wm, wy, sq_brts, yearmark) -- категория плюс частичная проверка
elseif (ispartdate(ingdate) and ispartdate(injdate)) then
mw.log("ingdate ".. (undate(ingdate) or ""))
mw.log("injdate ".. (undate(injdate) or ""))
mw.log("j1date " .. (undate(j1date ) or ""))
mw.log("j2date " .. (undate(j2date ) or ""))
mw.log("g1date " .. (undate(g1date ) or ""))
mw.log("g2date " .. (undate(g2date ) or ""))
mw.log("📏 " .. (tostring(partdist(ingdate,injdate)) or "").. " — " .. (tostring(partdist(injdate,ingdate)) or ""))
return glue(args[1],args[2],args[3],args[4],args[5],args[6])
-- частичный или полный вывод, категория
else
mw.log("ingdate ".. (undate(ingdate) or ""))
mw.log("injdate ".. (undate(injdate) or ""))
mw.log("j1date " .. (undate(j1date ) or ""))
mw.log("j2date " .. (undate(j2date ) or ""))
mw.log("g1date " .. (undate(g1date ) or ""))
mw.log("g2date " .. (undate(g2date ) or ""))
return err .. category.incomplete_parameters
end
end
return p
a4a91f134ad3e3b246b3a6681a4ae438da766df4
Модуль:Infocards
828
55
107
2023-05-29T15:51:46Z
wikipedia:ru>Putnik
0
переиспользование функции форматирования из [[Module:Dates]] для унификации
Scribunto
text/plain
local infocards = {}
local calculateAge = true
local dateCat = require( 'Module:Infocards/dateCat' )
local moduleDates = require( 'Module:Dates' )
--[[
Helper function that populates the argument list given that user may need to use a mix of
named and unnamed parameters. This is relevant because named parameters are not
identical to unnamed parameters due to string trimming, and when dealing with strings
we sometimes want to either preserve or remove that whitespace depending on the application.
]]
function infocards._getParameters( frame_args, arg_list )
local new_args = {}
local index = 1
local value
for i,arg in ipairs( arg_list ) do
value = frame_args[arg]
if value == nil then
value = frame_args[index]
index = index + 1
end
new_args[arg] = value
end
return new_args
end
function infocards.isBlank( someString )
return someString == nil or mw.ustring.match(someString, '^%s*$') ~= nil
end
function infocards.isDate ( frame )
local new_args = infocards._getParameters( frame.args, {'s', 't', 'f'} )
local s = new_args['s'] or ''
local t = new_args['t'] or ''
local f = new_args['f'] or ''
local result = infocards.isDateImpl ( s )
if (result) then
return t
else
return f
end
end
function infocards.isDateImpl ( s )
local converted = infocards.convertToDate ( s )
return converted ~= nil
end
function infocards.dateOfBirth( frame )
local new_args = infocards._getParameters( frame.args, {'dateOfBirth', 'dateOfDeath', 'suppressAge', 'nocat'} )
local dateOfBirth = new_args['dateOfBirth'] or ''
local dateOfDeath = new_args['dateOfDeath'] or ''
local suppressAge = new_args['suppressAge'] or ''
local nocat = new_args['nocat'] or mw.title.getCurrentTitle().nsText
return infocards.dateOfBirthImpl( dateOfBirth, dateOfDeath, suppressAge, nocat )
end
function infocards.dateOfBirthImpl( dateOfBirth, dateOfDeath, suppressAge, nocat )
local appendToCategory = infocards.isBlank( nocat )
if ( infocards.isBlank( dateOfBirth ) ) then
if ( appendToCategory ) then
return dateCat.categoryNoBirthDate
else
return ''
end
end
if ( mw.ustring.match( dateOfBirth, '^%s*неизвестн.%s*$' ) ~= nil
or mw.ustring.match( dateOfBirth, '^%s*%?%s*$' ) ~= nil ) then
if ( appendToCategory ) then
return "''неизвестно''" .. dateCat.categoryUnknownBirthDate
else
return "''неизвестно''"
end
end
local appendAge = not (suppressAge ~= '' or not calculateAge) and infocards.isBlank( dateOfDeath )
local parsedDate = infocards.convertToDate ( dateOfBirth )
if ( parsedDate == nil ) then
--[[ Temporary hack in order to enable export dates to wikidata ]]
local bDateStart = '<span class="no-wikidata" data-wikidata-property-id="P569">'
local bDateEnd = '</span>'
if ( appendToCategory ) then
return bDateStart .. dateOfBirth .. bDateEnd .. dateCat.categoryManualWikification
else
return bDateStart .. dateOfBirth .. bDateEnd
end
end
local result = infocards.formatDateImpl ( parsedDate, 'bday', appendToCategory and 'Родившиеся' or nil )
if ( appendAge ) then
-- TODO: месяцы и дни для (нескольких) новорождённых (см. новейшие [[Категория:Родившиеся в ГГГГ году]])
local age = infocards.age ( parsedDate, os.date("*t") )
if ( age and age < 125) then
result = result .. ' <span class="nowrap">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>'
end
if ( appendToCategory ) then
if (not age and parsedDate and parsedDate.year ) then
age = os.date('*t').year - parsedDate.year -- при неточной дате
end
if ( age ) then
if ( age > 115 ) then
result = result .. dateCat.categoryBigCurrentAge
elseif ( age >= 0 ) then
result = result .. dateCat.categoryBiographiesOfLivingPersons
else
result = result .. dateCat.categoryNegativeAge
end
end
end
end
return result
end
function infocards.dateOfDeath( frame )
local new_args = infocards._getParameters( frame.args, {'dateOfBirth', 'dateOfDeath', 'nocat'} )
local dateOfBirth = new_args['dateOfBirth'] or ''
local dateOfDeath = new_args['dateOfDeath'] or ''
local nocat = new_args['nocat'] or mw.title.getCurrentTitle().nsText
return infocards.dateOfDeathImpl( dateOfBirth, dateOfDeath, nocat )
end
function infocards.dateOfDeathImpl( dateOfBirth, dateOfDeath, nocat )
if ( infocards.isBlank( dateOfDeath ) ) then
return ''
end
local appendToCategory = infocards.isBlank( nocat )
if ( mw.ustring.match( dateOfDeath, '^%s*неизвестн.%s*$' ) ~= nil
or mw.ustring.match( dateOfDeath, '^%s*%?%s*$' ) ~= nil ) then
if ( appendToCategory ) then
return "''неизвестно''" .. dateCat.categoryUnknownDeathDate
else
return "''неизвестно''"
end
end
local parsedDateOfBirth = infocards.convertToDate ( dateOfBirth )
local parsedDateOfDeath = infocards.convertToDate ( dateOfDeath )
if ( parsedDateOfDeath == nil ) then
--[[ Temporary hack in order to enable export dates to wikidata ]]
local dDateStart = '<span class="no-wikidata" data-wikidata-property-id="P570">'
local dDateEnd = '</span>'
if ( appendToCategory ) then
return dDateStart .. dateOfDeath .. dDateEnd .. dateCat.categoryManualWikification
else
return dDateStart .. dateOfDeath .. dDateEnd
end
end
local result = infocards.formatDateImpl ( parsedDateOfDeath, 'dday', appendToCategory and 'Умершие' or nil )
if ( calculateAge ) then
local age = infocards.age ( parsedDateOfBirth, parsedDateOfDeath )
if ( age and age > 0 ) then
result = result .. ' <span class="nowrap">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>'
end
-- returns category to recently deceased persons
local unixAvailable, unixDateOfDeath = pcall(function()
local r = os.time(parsedDateOfDeath)
if ( r ~= os.time() ) then
return r
end
error()
end)
if (appendToCategory) then
if ( unixAvailable and os.time() - unixDateOfDeath < 31536000 ) then
result = result .. dateCat.categoryRecentlyDeceased
elseif (age and age < 0) then
result = result .. dateCat.categoryNegativeAge
end
end
end
return result
end
function infocards.age( parsedBirthDate, parsedFinishDate )
if ( parsedBirthDate == nil or parsedFinishDate == nil ) then
return nil
end
local bd = parsedBirthDate["day"]
local bm = parsedBirthDate["month"]
local by = parsedBirthDate["year"]
local dd = parsedFinishDate["day"]
local dm = parsedFinishDate["month"]
local dy = parsedFinishDate["year"]
if ( bd and bm and by and dd and dm and dy ) then
if ( dm > bm or ( dm == bm and dd >= bd ) ) then
return dy - by
else
return dy - by - 1
end
else
return nil
end
end
function infocards.formatDateImpl( parsedDate, infocardClass, categoryNamePrefix )
local datePart = '<span class="nowrap">'
--Temporary hack in order to enable export dates to wikidata
if infocardClass == "bday" then
datePart = '<span class="no-wikidata" data-wikidata-property-id="P569">'
elseif infocardClass == "dday" then
datePart = '<span class="no-wikidata" data-wikidata-property-id="P570">'
end
local t1 = { day = parsedDate.osday, month = parsedDate.osmonth, year = parsedDate.osyear }
local t2 = { day = parsedDate.day, month = parsedDate.month, year = parsedDate.year }
datePart = datePart .. moduleDates.formatWikiImpl( t1, t2, infocardClass, categoryNamePrefix )
datePart = datePart .. '</span>'
return datePart
end
function infocards.convertToDate( possibleDateString )
possibleDateString = mw.ustring.gsub( possibleDateString, '−', '-')
local simpleDate = mw.ustring.match(possibleDateString, '^%s*([%-%d%.]+)%s*$', 0)
if ( simpleDate ) then
return infocards.convertToDateNewStylePart( simpleDate )
end
local complexDate1, complexDate2 = mw.ustring.match(possibleDateString, '^%s*([%-%d%.]+)%s*%(([%-%d%.]+)%)%s*$', 0)
if ( complexDate1 and complexDate2) then
local table1 = infocards.convertToDateNewStylePart( complexDate1 )
local table2 = infocards.convertToDateOldStylePart( complexDate2 )
if ( table1 and table2 ) then
return {
year = table1["year"], month = table1["month"], day = table1["day"],
osyear = table2["year"], osmonth = table2["month"], osday = table2["day"]
}
else
return nil
end
end
return nil
end
function infocards.convertToDateNewStylePart( possibleDateString )
local ny = mw.ustring.match(possibleDateString, '^(%-?%d+)$', 0)
if (ny ~= nil) then
return {year = tonumber(ny)}
end
return infocards.convertToDateCommonPart( possibleDateString )
end
function infocards.convertToDateOldStylePart( possibleDateString )
local nd = mw.ustring.match(possibleDateString, '^(%-?%d+)$', 0)
if (nd ~= nil) then
return {day = tonumber(nd)}
end
return infocards.convertToDateCommonPart( possibleDateString )
end
function infocards.convertToDateCommonPart( possibleDateString )
local sDay, sMonth, sYear
local day, month, year
sDay, sMonth, sYear = mw.ustring.match( possibleDateString, '^(%d?%d)%.(%d?%d)%.(%-?%d+)$', 0 )
if sDay ~= nil and sMonth ~= nil and sYear ~= nil then
day = tonumber( sDay )
month = tonumber( sMonth )
year = tonumber( sYear )
if day >= 1 and day <= 32 and month >= 1 and month <= 12 then
return { day = day, month = month, year = year }
end
end
sDay, sMonth = mw.ustring.match( possibleDateString, '^(%d?%d)%.(%d?%d+)$', 0 )
if sDay ~= nil and sMonth ~= nil then
day = tonumber( sDay )
month = tonumber( sMonth )
if day >= 1 and day <= 32 and month >= 1 and month <= 12 then
return { day = day, month = month }
end
end
sMonth, sYear = mw.ustring.match( possibleDateString, '^(%d?%d)%.(%-?%d+)$', 0 )
if sMonth ~= nil and sYear ~= nil then
month = tonumber( sMonth )
year = tonumber( sYear )
if month >= 1 and month <= 12 then
return { month = month, year = year }
end
end
return nil
end
return infocards
6c1e746d6605d4d101f6aa9fd3e4824b60c64ef7
Шаблон:Карточка/оригинал имени
10
45
87
2023-07-04T10:53:34Z
wikipedia:ru>Wikisaurus
0
wikitext
text/x-wiki
{{wikidata|p1559[language!:ru]|{{{1|}}}|before={{{before|}}}|separator=<br>|conjunction=<br>|monolingualLangTemplate={{{monolingualLangTemplate|lang}}}|from={{{from|}}}}}<!--
-->{{#if:{{NAMESPACE}}||{{#if:{{{1|}}}|{{#ifeq:{{#invoke:String|find|{{{1|}}}|span}}|0|[[Категория:Википедия:Статьи с оригиналом имени без шаблона lang-XX]]}}}}}}<noinclude>{{doc}}</noinclude>
a294e3f7f61c5206ca5671b72e21804d7a32fcbc
Шаблон:Флагификация/флагификация
10
43
83
2023-07-28T15:53:15Z
wikipedia:ru>Stjn
0
не изменять размер в мобильной версии (на всякий случай)
wikitext
text/x-wiki
<span class="nowrap" data-sort-value="{{{shortname alias|{{{alias}}}}}}"><span class="flagicon">[[File:{{{flag alias-{{{variant}}}|{{{flag alias}}}}}}|class=noresize|link=|alt=|{{#if: {{{размер|}}} | {{{размер}}} | 22x20px }}|{{{border-{{{variant}}}|{{{border|border}}}}}}]]</span> [[{{{alias}}}|<span class="wrap">{{{shortname alias-{{{variant}}}|{{{shortname alias|{{{alias}}}}}}}}}</span>]]</span><noinclude>{{doc}}</noinclude>
8403cde4528b4d7df313d2e82aeb40b0bb66c2c2
Шаблон:Сначала имя
10
51
99
2023-11-15T18:34:52Z
wikipedia:ru>Stjn
0
читаемость
wikitext
text/x-wiki
{{safesubst:<noinclude />#ifexpr: {{safesubst:<noinclude />str find|{{safesubst:<noinclude />До символа|{{{1}}}|(}}|,}} = -1 <!--
-->|{{safesubst:<noinclude />До символа|{{{1}}}|(}}<!--
-->|{{safesubst:<noinclude />trim|{{safesubst:<noinclude />После символа|{{safesubst:<noinclude />До символа|{{{1}}}|(}}|,}}}} {{safesubst:<noinclude />До символа|{{safesubst:<noinclude />До символа|{{{1}}}|(}}|,}}<!--
-->}}<noinclude>
{{doc}}
</noinclude>
c3a2e3e13dba0ae595a7c147ca692be2eb183f38
Шаблон:Легенда
10
88
173
2024-01-07T19:41:21Z
wikipedia:ru>Stjn
0
у нас ещё и это невозможно
wikitext
text/x-wiki
<includeonly><!--
--><templatestyles src="Шаблон:Легенда/styles.css" /><!--
--><span class="ts-legend {{#ifeq: {{{3|}}} | inline | ts-legend-inline }} legend" style="{{#if: {{{8|}}} | font-size: {{{8}}}; }}"><!--
--><span class="ts-legend-color legend-color mw-no-invert {{{class|}}}" style="<!--
-->{{#if: {{{4|}}} | border: {{{4}}}; | {{#if: {{{1|}}} | border: 0px solid {{{1}}};}}}}<!--
-->{{#if: {{{5|}}} | border-radius: {{{5}}};}}<!--
-->{{#if: {{{1|}}} | background: {{{1}}};}}<!--
-->{{#if: {{{6|}}} | color: {{{6}}}; }}<!--
-->" {{#if: {{{9|}}} | title="{{{9}}}" | {{#if: {{{1|}}} | title="{{{1}}}"}} }}><!--
-->{{#if: {{{alt|}}}{{{7|}}}
| <span class="ts-legend-text legend-text" style="{{#if:{{{alt|}}} | color:{{{1|}}};}}font-family: monospace, monospace;">{{#if: {{{7|}}} | {{{7}}} | }}</span>
}}<!--
--></span><!--
--> {{{2|}}}<!--
--></span><!--
--></includeonly><noinclude>
{{doc}}
<!-- Пожалуйста, добавляйте категории и интервики на страницу документации! -->
</noinclude>
362927ba47a0f5b2dcf9de3f17dbfbc8eaba4b89
Шаблон:Легенда/styles.css
10
110
217
2024-01-07T20:03:02Z
wikipedia:ru>Q-bit array
0
Защитил страницу [[Шаблон:Легенда/styles.css]]: критический шаблон или модуль ([Редактирование=администраторы и инженеры] (бессрочно) [Переименование=администраторы и инженеры] (бессрочно))
text
text/plain
/* Скопировано из [[:en:Template:Legend/styles.css]] с изменениями */
.ts-legend {
page-break-inside: avoid;
break-inside: avoid-column;
display: block;
font-size: 90%;
}
.thumb .ts-legend,
figcaption .ts-legend {
font-size: inherit;
}
.ts-legend-inline {
display: inline-block;
}
.ts-legend-color {
display: inline-block;
min-width: 1.25em;
height: 1.25em;
line-height: 1.25;
margin: 1px 0;
text-align: center;
border: 1px solid black;
color: black;
vertical-align: middle;
}
/*empty for now, but part of the design!*/
/*.ts-legend-text {}*/
/* [[Категория:Шаблоны:Подстраницы CSS]] */
92f4aefe4d4206899f554e9262090e50a27a5171
Модуль:Delink
828
39
75
2024-02-28T16:27:08Z
wikipedia:ru>Dima st bk
0
sync with enwiki, see authors of this version https://en.wikipedia.org/w/index.php?title=Module:Delink&oldid=1208348327
Scribunto
text/plain
-- This module de-links most wikitext.
require("strict")
local yesno = require("Module:Yesno")
local p = {}
local getArgs
local function delinkReversePipeTrick(s)
if s:match("^%[%[|.*[|\n]") then -- Check for newlines or multiple pipes.
return s
end
return s:match("%[%[|(.*)%]%]")
end
local function delinkPipeTrick(s)
-- We need to deal with colons, brackets, and commas, per [[Help:Pipe trick]].
-- First, remove the text before the first colon, if any.
if s:match(":") then
s = s:match("%[%[.-:(.*)|%]%]")
-- If there are no colons, grab all of the text apart from the square brackets and the pipe.
else
s = s:match("%[%[(.*)|%]%]")
end
-- Next up, brackets and commas.
if s:match("%(.-%)$") then -- Brackets trump commas.
s = s:match("(.-) ?%(.-%)$")
elseif s:match(",") then -- If there are no brackets, display only the text before the first comma.
s = s:match("(.-),.*$")
end
return s
end
-- Return wikilink target |wikilinks=target
local function getDelinkedTarget(s)
local result = s
-- Deal with the reverse pipe trick.
if result:match("%[%[|") then
return delinkReversePipeTrick(result)
end
result = mw.uri.decode(result, "PATH") -- decode percent-encoded entities. Leave underscores and plus signs.
result = mw.text.decode(result, true) -- decode HTML entities.
-- Check for bad titles. To do this we need to find the
-- title area of the link, i.e. the part before any pipes.
local target_area
if result:match("|") then -- Find if we're dealing with a piped link.
target_area = result:match("^%[%[(.-)|.*%]%]")
else
target_area = result:match("^%[%[(.-)%]%]")
end
-- Check for bad characters.
if mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") and mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") ~= "?" then
return s
end
return target_area
end
local function getDelinkedLabel(s)
local result = s
-- Deal with the reverse pipe trick.
if result:match("%[%[|") then
return delinkReversePipeTrick(result)
end
result = mw.uri.decode(result, "PATH") -- decode percent-encoded entities. Leave underscores and plus signs.
result = mw.text.decode(result, true) -- decode HTML entities.
-- Check for bad titles. To do this we need to find the
-- title area of the link, i.e. the part before any pipes.
local target_area
if result:match("|") then -- Find if we're dealing with a piped link.
target_area = result:match("^%[%[(.-)|.*%]%]")
else
target_area = result:match("^%[%[(.-)%]%]")
end
-- Check for bad characters.
if mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") and mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") ~= "?" then
return s
end
-- Check for categories, interwikis, and files.
local colon_prefix = result:match("%[%[(.-):.*%]%]") or "" -- Get the text before the first colon.
local ns = mw.site.namespaces[colon_prefix] -- see if this is a known namespace
if mw.language.isKnownLanguageTag(colon_prefix) or (ns and (ns.canonicalName == "File" or ns.canonicalName == "Category")) then
return ""
end
-- Remove the colon if the link is using the [[Help:Colon trick]].
if result:match("%[%[:") then
result = "[[" .. result:match("%[%[:(.*%]%])")
end
-- Deal with links using the [[Help:Pipe trick]].
if mw.ustring.match(result, "^%[%[[^|]*|%]%]") then
return delinkPipeTrick(result)
end
-- Find the display area of the wikilink
if result:match("|") then -- Find if we're dealing with a piped link.
result = result:match("^%[%[.-|(.+)%]%]")
-- Remove new lines from the display of multiline piped links,
-- where the pipe is before the first new line.
result = result:gsub("\n", "")
else
result = result:match("^%[%[(.-)%]%]")
end
return result
end
local function delinkURL(s)
-- Assume we have already delinked internal wikilinks, and that
-- we have been passed some text between two square brackets [foo].
-- If the text contains a line break it is not formatted as a URL, regardless of other content.
if s:match("\n") then
return s
end
-- Check if the text has a valid URL prefix and at least one valid URL character.
local valid_url_prefixes = {"//", "http://", "https://", "ftp://", "gopher://", "mailto:", "news:", "irc://"}
local url_prefix
for _ ,v in ipairs(valid_url_prefixes) do
if mw.ustring.match(s, '^%[' .. v ..'[^"%s].*%]' ) then
url_prefix = v
break
end
end
-- Get display text
if not url_prefix then
return s
end
s = s:match("^%[" .. url_prefix .. "(.*)%]") -- Grab all of the text after the URL prefix and before the final square bracket.
s = s:match('^.-(["<> ].*)') or "" -- Grab all of the text after the first URL separator character ("<> ).
s = mw.ustring.match(s, "^%s*(%S.*)$") or "" -- If the separating character was a space, trim it off.
local s_decoded = mw.text.decode(s, true)
if mw.ustring.match(s_decoded, "%c") then
return s
end
return s_decoded
end
local function delinkLinkClass(text, pattern, delinkFunction)
if type(text) ~= "string" then
error("Attempt to de-link non-string input.", 2)
end
if type(pattern) ~= "string" or mw.ustring.sub(pattern, 1, 1) ~= "^" then
error('Invalid pattern detected. Patterns must begin with "^".', 2)
end
-- Iterate over the text string, and replace any matched text. using the
-- delink function. We need to iterate character by character rather
-- than just use gsub, otherwise nested links aren't detected properly.
local result = ""
while text ~= "" do
-- Replace text using one iteration of gsub.
text = mw.ustring.gsub(text, pattern, delinkFunction, 1)
-- Append the left-most character to the result string.
result = result .. mw.ustring.sub(text, 1, 1)
text = mw.ustring.sub(text, 2, -1)
end
return result
end
function p._delink(args)
local text = args[1] or ""
if yesno(args.markers) == true then
text = mw.text.killMarkers(text) -- [[Help:Strip markers]]
end
if yesno(args.refs) == true then
-- Remove any [[Help:Strip markers]] representing ref tags. In most situations
-- this is not a good idea - only use it if you know what you are doing!
text = mw.ustring.gsub(text, "UNIQ%w*%-ref%-%d*%-QINU", "")
end
if not (yesno(args.comments) == false) then
text = text:gsub("<!%-%-.-%-%->", "") -- Remove html comments.
end
if not (yesno(args.wikilinks) == false) and args.wikilinks ~= "target" then
-- De-link wikilinks and return the label portion of the wikilink.
text = delinkLinkClass(text, "^%[%[.-%]%]", getDelinkedLabel)
elseif args.wikilinks == "target" then
-- De-link wikilinks and return the target portions of the wikilink.
text = delinkLinkClass(text, "^%[%[.-%]%]", getDelinkedTarget)
end
if not (yesno(args.urls) == false) then
text = delinkLinkClass(text, "^%[.-%]", delinkURL) -- De-link URLs.
end
if not (yesno(args.whitespace) == false) then
-- Replace single new lines with a single space, but leave double new lines
-- and new lines only containing spaces or tabs before a second new line.
text = mw.ustring.gsub(text, "([^\n \t][ \t]*)\n([ \t]*[^\n \t])", "%1 %2")
text = text:gsub("[ \t]+", " ") -- Remove extra tabs and spaces.
end
return text
end
function p.delink(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
return p._delink(getArgs(frame, {wrappers = 'Template:Delink'}))
end
return p
eb6cae0d369f288b0b1600633d9bf7874cefdcbc
Модуль:Message box
828
14
25
2024-03-25T18:05:03Z
wikipedia:ru>Stjn
0
fix
Scribunto
text/plain
-- This is a meta-module for producing message box templates, including
-- {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.
-- Load necessary modules.
require('strict')
local getArgs
local categoryHandler = require('Module:Category handler')._main
local yesno = require('Module:Yesno')
local boxDate = require('Module:Calendar').bxDate;
-- Get a language object for formatDate and ucfirst.
local lang = mw.language.getContentLanguage()
-- Define constants
local CONFIG_MODULE = 'Module:Message box/configuration'
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getTitleObject(...)
-- Get the title object, passing the function through pcall
-- in case we are over the expensive function count limit.
local success, title = pcall(mw.title.new, ...)
if success then
return title
end
end
local function union(t1, t2)
-- Returns the union of two arrays.
local vals = {}
for i, v in ipairs(t1) do
vals[v] = true
end
for i, v in ipairs(t2) do
vals[v] = true
end
local ret = {}
for k in pairs(vals) do
table.insert(ret, k)
end
table.sort(ret)
return ret
end
local function getArgNums(args, prefix)
local nums = {}
for k, v in pairs(args) do
local num = mw.ustring.match(tostring(k), '^' .. prefix .. '([1-9]%d*)$')
if num then
table.insert(nums, tonumber(num))
end
end
table.sort(nums)
return nums
end
-- локальная обёртка, игнорирует таблицу с номерами дня, месяца и года
local function formatDate(txtDateIn, strFormat, params)
local txtDateOut, date, status = boxDate(txtDateIn, strFormat, params)
if status.brk then
return error(status.errorText)
else
return txtDateOut
end
end
--------------------------------------------------------------------------------
-- Box class definition
--------------------------------------------------------------------------------
local MessageBox = {}
MessageBox.__index = MessageBox
function MessageBox.new(boxType, args, cfg)
args = args or {}
local obj = {}
-- Set the title object and the namespace.
obj.title = getTitleObject(args.page) or mw.title.getCurrentTitle()
-- Set the config for our box type.
obj.cfg = cfg[boxType]
if not obj.cfg then
local ns = obj.title.namespace
-- boxType is "mbox" or invalid input
if ns == 0 then
obj.cfg = cfg.ambox -- main namespace
elseif ns == 6 then
obj.cfg = cfg.imbox -- file namespace
elseif ns == 14 then
obj.cfg = cfg.cmbox -- category namespace
else
local nsTable = mw.site.namespaces[ns]
if nsTable and nsTable.isTalk then
obj.cfg = cfg.tmbox -- any talk namespace
else
obj.cfg = cfg.ombox -- other namespaces or invalid input
end
end
end
-- Set the arguments, and remove all blank arguments except for the ones
-- listed in cfg.allowBlankParams.
do
local newArgs = {}
for k, v in pairs(args) do
if v ~= '' then
newArgs[k] = v
end
end
for i, param in ipairs(obj.cfg.allowBlankParams or {}) do
newArgs[param] = args[param]
end
obj.args = newArgs
end
-- Define internal data structure.
obj.categories = {}
obj.classes = {}
return setmetatable(obj, MessageBox)
end
function MessageBox:addCat(ns, cat, sort)
if not cat then
return nil
end
if sort then
cat = string.format('[[Категория:%s|%s]]', cat, sort)
else
cat = string.format('[[Категория:%s]]', cat)
end
self.categories[ns] = self.categories[ns] or {}
table.insert(self.categories[ns], cat)
end
function MessageBox:addClass(class)
if not class then
return nil
end
table.insert(self.classes, class)
end
function MessageBox:setParameters()
local args = self.args
local cfg = self.cfg
-- Get type data.
self.type = args.type
local typeData = cfg.types[self.type]
self.invalidTypeError = cfg.showInvalidTypeError
and self.type
and not typeData
typeData = typeData or cfg.types[cfg.default]
self.typeClass = typeData.class
self.typeImage = typeData.image
-- Find if the box has been wrongly substituted.
self.isSubstituted = cfg.substCheck and args.subst == 'SUBST'
-- Find whether we are using a small message box.
self.isSmall = cfg.allowSmall and (
cfg.smallParam and args.small == cfg.smallParam
or not cfg.smallParam and yesno(args.small)
)
-- Add attributes, classes and styles.
self.id = args.id
self.name = args.name
if self.name then
self:addClass('mbox-' .. string.gsub(self.name,' ','_'))
end
if yesno(args.plainlinks) ~= false then
self:addClass('plainlinks')
end
for _, class in ipairs(cfg.classes or {}) do
self:addClass(class)
end
if self.isSmall then
self:addClass(cfg.smallClass or 'mbox-small')
end
self:addClass(self.typeClass)
self:addClass(args.class)
self.style = args.style
self.attrs = args.attrs
self.dataLabel1 = args['data-label-1']
self.dataLabel2 = args['data-label-2']
self.dataLabel3 = args['data-label-3']
self.dataValue1 = args['data-value-1']
self.dataValue2 = args['data-value-2']
self.dataValue3 = args['data-value-3']
-- Set text style.
self.textstyle = args.textstyle
-- Find if we are on the template page or not. This functionality is only
-- used if useCollapsibleTextFields is set, or if both cfg.templateCategory
-- and cfg.templateCategoryRequireName are set.
self.useCollapsibleTextFields = cfg.useCollapsibleTextFields
if self.useCollapsibleTextFields
or cfg.templateCategory
and cfg.templateCategoryRequireName
then
self.name = args.name
if self.name then
local templateName = mw.ustring.match(
self.name,
'^[tT][eE][mM][pP][lL][aA][tT][eE][%s_]*:[%s_]*(.*)$'
) or self.name
templateName = ('Template:' .. templateName) or ('Шаблон:' .. templateName)
self.templateTitle = getTitleObject(templateName)
end
self.isTemplatePage = self.templateTitle
and mw.title.equals(self.title, self.templateTitle)
end
-- Process data for collapsible text fields. At the moment these are only
-- used in {{ambox}}.
if self.useCollapsibleTextFields then
-- Get the self.issue value.
if self.isSmall and args.smalltext then
self.issue = args.smalltext
else
if args.sect and args.sect ~= '' or nil then
local issue_sect = args.issue_sect
issue_sect = type(issue_sect) == 'string' and issue_sect ~= '' and issue_sect or nil
local text_sect = args.text_sect
text_sect = type(text_sect) == 'string' and text_sect ~= '' and text_sect or nil
local issues = {}
table.insert(issues, issue_sect)
table.insert(issues, text_sect)
self.issue = table.concat(issues, ' ')
else
local issue = args.issue
issue = type(issue) == 'string' and issue ~= '' and issue or nil
local text = args.text
text = type(text) == 'string' and text or nil
local issues = {}
table.insert(issues, issue)
table.insert(issues, text)
self.issue = table.concat(issues, ' ')
end
end
-- Get the self.talk value.
local talk = args.talk
-- Show talk links on the template page or template subpages if the talk
-- parameter is blank.
if talk == ''
and self.templateTitle
and (
mw.title.equals(self.templateTitle, self.title)
or self.title:isSubpageOf(self.templateTitle)
)
then
talk = '#'
elseif talk == '' then
talk = nil
end
if talk then
-- If the talk value is a talk page, make a link to that page. Else
-- assume that it's a section heading, and make a link to the talk
-- page of the current page with that section heading.
local talkTitle = getTitleObject(talk)
local talkArgIsTalkPage = true
if not talkTitle or not talkTitle.isTalkPage then
talkArgIsTalkPage = false
talkTitle = getTitleObject(
self.title.text,
mw.site.namespaces[self.title.namespace].talk.id
)
end
if talkTitle and talkTitle.exists then
local talkText = 'Соответствующую дискуссию можно найти на'
if talkArgIsTalkPage then
talkText = string.format(
'%s [[%s|%s]].',
talkText,
talk,
talkTitle.prefixedText
)
else
talkText = string.format(
'%s [[%s#%s|странице обсуждения]].',
talkText,
talkTitle.prefixedText,
talk
)
end
self.talk = talkText
end
end
-- Get other values.
self.fix = args.fix ~= '' and args.fix or nil
local date
if args.date and args.date ~= '' then
local status, result = pcall(formatDate, args.date)
if status then
date = string.format("(<span class='date'>%s</span>)", result)
else
date = string.format("<span class='error'>(Строка «%s» не является верной датой, пожалуйста, укажите дату в формате <code>ГГГГ-ММ-ДД</code>)</span>", args.date)
end
elseif args.date == '' and self.isTemplatePage then
date = string.format("(<span class='date'>%s</span>)", formatDate( lang:formatDate('Y-m-d') ) ) -- тут возникновения ошибки, связанной с пользовательским вводом, не будет
end
if date then
self.date = string.format(" <span class='mbox-date'>''%s''</span>", date)
end
self.info = args.info
if yesno(args.removalnotice) then
self.removalNotice = cfg.removalNotice
end
if args.shortFix then
self.shortFix = args.shortFix
end
end
-- Set the non-collapsible text field. At the moment this is used by all box
-- types other than ambox, and also by ambox when small=yes.
if self.isSmall then
self.text = args.smalltext or args.text
else
self.text = args.text
self.textsmall = args['text-small']
end
-- Set the below row.
self.below = cfg.below and args.below
-- General image settings.
self.imageCellDiv = not self.isSmall and cfg.imageCellDiv
self.imageEmptyCell = cfg.imageEmptyCell
if cfg.imageEmptyCellStyle then
self.imageEmptyCellStyle = 'border:none;padding:0px;width:1px'
end
-- Left image settings.
local imageLeft = self.isSmall and args.smallimage or args.image
if cfg.imageCheckBlank and imageLeft ~= 'blank' and imageLeft ~= 'none' and imageLeft ~= ''
or not cfg.imageCheckBlank and imageLeft ~= 'none'
then
self.imageLeft = imageLeft
if not imageLeft then
local imageSize = self.isSmall
and (cfg.imageSmallSize or '30x30px')
or cfg.imageSize
or '40x40px'
self.imageLeft = string.format('[[File:%s|%s|alt=]]', self.typeImage
or 'Information icon4.svg', imageSize)
end
end
-- Right image settings.
local imageRight = self.isSmall and args.smallimageright or args.imageright
if not (cfg.imageRightNone and imageRight == 'none') then
self.imageRight = imageRight
end
-- set templatestyles
self.base_templatestyles = cfg.templatestyles
end
function MessageBox:setMainspaceCategories()
local args = self.args
local cfg = self.cfg
local date = nil
if not cfg.allowMainspaceCategories then
return nil
end
local nums = {}
for _, prefix in ipairs{'cat', 'category', 'all'} do
args[prefix .. '1'] = args[prefix]
nums = union(nums, getArgNums(args, prefix))
end
-- The following is roughly equivalent to the old {{Ambox/category}}.
local status, result = pcall(formatDate, args.date, 'xg Y')
if status then
date = result
end
date = type(date) == 'string' and date
local preposition = 'с'
local suffix = 'года'
for _, num in ipairs(nums) do
local mainCat = args['cat' .. tostring(num)]
or args['category' .. tostring(num)]
local allCat = args['all' .. tostring(num)]
mainCat = type(mainCat) == 'string' and mainCat
allCat = type(allCat) == 'string' and allCat
if mainCat and date and date ~= '' then
local catTitle = string.format('%s %s %s %s', mainCat, preposition, date, suffix)
self:addCat(0, catTitle)
catTitle = getTitleObject('Категория:' .. catTitle)
local status, result = pcall(formatDate, args.date)
if not status then
self:addCat(0, 'Википедия:Статьи с недопустимым параметром даты в шаблоне-сообщении')
end
elseif mainCat and (not date or date == '') then
self:addCat(0, mainCat)
end
if allCat then
self:addCat(0, allCat)
end
end
end
function MessageBox:setTemplateCategories()
local args = self.args
local cfg = self.cfg
-- Add template categories.
if cfg.templateCategory then
if cfg.templateCategoryRequireName then
if self.isTemplatePage then
self:addCat(10, cfg.templateCategory)
end
elseif not self.title.isSubpage then
self:addCat(10, cfg.templateCategory)
end
end
-- Add template error categories.
if cfg.templateErrorCategory then
local templateErrorCategory = cfg.templateErrorCategory
local templateCat, templateSort
if not self.name and not self.title.isSubpage then
templateCat = templateErrorCategory
elseif self.isTemplatePage then
local paramsToCheck = cfg.templateErrorParamsToCheck or {}
local count = 0
for i, param in ipairs(paramsToCheck) do
if not args[param] then
count = count + 1
end
end
if count > 0 then
templateCat = templateErrorCategory
templateSort = tostring(count)
end
if self.categoryNums and #self.categoryNums > 0 then
templateCat = templateErrorCategory
templateSort = 'C'
end
end
self:addCat(10, templateCat, templateSort)
end
end
function MessageBox:setAllNamespaceCategories()
-- Set categories for all namespaces.
if self.invalidTypeError then
local allSort = (self.title.namespace == 0 and 'Main:' or '') .. self.title.prefixedText
self:addCat('all', 'Википедия:Необходимо исправить параметр в шаблоне-сообщении', allSort)
end
if self.isSubstituted then
self:addCat('all', 'Википедия:Страницы с ошибочно подставленными шаблонами')
end
if self.isSmall then
self:addCat(0, 'Википедия:Страницы с малыми шаблонами-сообщениями')
end
end
function MessageBox:setCategories()
if self.title.namespace == 0 then
self:setMainspaceCategories()
elseif self.title.namespace == 10 then
self:setTemplateCategories()
end
self:setAllNamespaceCategories()
end
function MessageBox:renderCategories()
-- Convert category tables to strings and pass them through
-- [[Module:Category handler]].
return categoryHandler{
main = table.concat(self.categories[0] or {}),
template = table.concat(self.categories[10] or {}),
all = table.concat(self.categories.all or {}),
nocat = self.args.nocat,
page = self.args.page
}
end
function MessageBox:export()
local root = mw.html.create()
-- Add the subst check error.
if self.isSubstituted and self.name then
root:tag('b')
:addClass('error')
:wikitext(string.format(
'Шаблон <code>%s[[Шаблон:%s|%s]]%s</code> был неккоректно подставлен.',
mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}')
))
end
-- Conditional TemplateStyles loading
if self.base_templatestyles then
local frame = mw.getCurrentFrame()
root:wikitext(frame:extensionTag{
name = 'templatestyles',
args = { src = self.base_templatestyles },
})
end
-- Create the box table.
local boxTable = root:tag('table')
boxTable:attr('id', self.id or nil)
for i, class in ipairs(self.classes or {}) do
boxTable:addClass(class or nil)
end
boxTable
:cssText(self.style or nil)
:attr('role', 'presentation')
if self.dataLabel1 then
boxTable:attr('data-' .. self.dataLabel1, self.dataValue1)
end
if self.dataLabel2 then
boxTable:attr('data-' .. self.dataLabel2, self.dataValue2)
end
if self.dataLabel3 then
boxTable:attr('data-' .. self.dataLabel3, self.dataValue3)
end
if self.attrs then
boxTable:attr(self.attrs)
end
-- Add the left-hand image.
local row = boxTable:tag('tr')
if self.imageLeft then
local imageLeftCell = row:tag('td'):addClass('mbox-image')
if self.imageCellDiv then
-- If we are using a div, redefine imageLeftCell so that the image
-- is inside it. Divs use style="width: 52px;", which limits the
-- image width to 52px. If any images in a div are wider than that,
-- they may overlap with the text or cause other display problems.
imageLeftCell = imageLeftCell:tag('div'):css('width', '52px')
end
imageLeftCell:wikitext(self.imageLeft or nil)
elseif self.imageEmptyCell then
-- Some message boxes define an empty cell if no image is specified, and
-- some don't. The old template code in templates where empty cells are
-- specified gives the following hint: "No image. Cell with some width
-- or padding necessary for text cell to have 100% width."
row:tag('td')
:addClass('mbox-empty-cell')
:cssText(self.imageEmptyCellStyle or nil)
end
-- Add the text.
local textCell = row:tag('td'):addClass('mbox-text')
if self.useCollapsibleTextFields then
-- The message box uses advanced text parameters that allow things to be
-- collapsible. At the moment, only ambox uses this.
textCell:cssText(self.textstyle or nil)
local textCellDiv = textCell:tag('div')
textCellDiv
:addClass('mbox-text-div')
:wikitext(self.issue or nil)
local textsmallCellDiv = textCell:tag('div')
textsmallCellDiv
:addClass('mbox-textsmall-div hide-when-compact')
:cssText(self.textsmallstyle)
:wikitext(self.textsmall or nil)
if (self.talk or self.fix) and not self.isSmall then
textsmallCellDiv:tag('span')
:addClass('hide-when-compact')
:wikitext(self.fix and (' ' .. self.fix) or nil)
:wikitext(self.talk and (' ' .. self.talk) or nil)
end
if self.textsmall or self.fix or self.talk then
textsmallCellDiv:wikitext(self.date and (' ' .. self.date) or nil)
else
textCellDiv:wikitext(self.date and (' ' .. self.date) or nil)
end
if self.info and not self.isSmall then
textsmallCellDiv
:tag('span')
:addClass('hide-when-compact')
:wikitext(self.info and (' ' .. self.info) or nil)
end
if self.removalNotice then
textsmallCellDiv:tag('small')
:addClass('hide-when-compact')
:tag('i')
:wikitext(string.format(" (%s)", self.removalNotice))
end
if self.shortFix then
textCell:tag('div')
:addClass('mbox-multiply')
:tag('span')
:wikitext(string.format("%s", self.shortFix))
:tag('span')
:wikitext(self.date and (' ' .. self.date) or nil)
end
else
-- Default text formatting - anything goes.
textCell
:cssText(self.textstyle or nil)
:wikitext(self.text or nil)
end
-- Add the right-hand image.
if self.imageRight then
local imageRightCell = row:tag('td'):addClass('mbox-imageright')
if self.imageCellDiv then
-- If we are using a div, redefine imageRightCell so that the image
-- is inside it.
imageRightCell = imageRightCell:tag('div'):css('width', '52px')
end
imageRightCell
:wikitext(self.imageRight or nil)
end
-- Add the below row.
if self.below then
boxTable:tag('tr')
:tag('td')
:attr('colspan', self.imageRight and '3' or '2')
:addClass('mbox-text')
:cssText(self.textstyle or nil)
:wikitext(self.below or nil)
end
-- Add error message for invalid type parameters.
if self.invalidTypeError then
root:tag('div')
:css('text-align', 'center')
:wikitext(string.format(
'Этот шаблон-сообщение использует неверный параметр "type=%s", необходимо исправить.',
self.type or ''
))
end
-- Add categories.
root:wikitext(self:renderCategories() or nil)
return tostring(root)
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p, mt = {}, {}
function p._exportClasses()
-- For testing.
return {
MessageBox = MessageBox
}
end
function p.main(boxType, args, cfgTables)
local box = MessageBox.new(boxType, args, cfgTables or mw.loadData(CONFIG_MODULE))
box:setParameters()
box:setCategories()
return box:export()
end
function mt.__index(t, k)
return function (frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
return t.main(k, getArgs(frame, {trim = false, removeBlanks = false}))
end
end
return setmetatable(p, mt)
f2539b657a9cdadde7c0dd5ad270d3095b2bdd54
Шаблон:Очистить кэш
10
94
185
2024-03-27T11:58:48Z
wikipedia:ru>Stjn
0
не помещать на все страницы ежедневную очистку кэша
wikitext
text/x-wiki
<!-- Класс purgelink и атрибут data-pagename используются в [[MediaWiki:Common.js]], чтобы очищать кэш без перехода на отдельную страницу --><span class="noprint purgelink" {{#if: {{{2|}}} | data-pagename="{{{2}}}" }}>{{выполнить скрипт|purgeLink}}[[Special:Purge/{{#if: {{{2|}}} | {{{2}}} | {{FULLPAGENAME}} }}|{{#if: {{{1|}}} | {{{1}}} | Очистить кэш }}]]</span>{{#ifeq: {{NAMESPACE}}{{{nocat|}}}
| {{ns:10}} <!-- Шаблон -->
| {{очищать кэш|ежедневно}}
}}<noinclude>{{doc}}</noinclude>
be6695060ca61d2125386d02d3a19109c0e7c27b
Модуль:Yesno
828
12
21
2024-03-30T22:30:54Z
wikipedia:ru>Stjn
0
кириллическая у из-за невозможности различить от латинской
Scribunto
text/plain
-- Function allowing for consistent treatment of boolean-like wikitext input.
-- It works similarly to the template {{yesno}}.
return function (val, default)
-- If your wiki uses non-ascii characters for any of "yes", "no", etc., you
-- should replace "val:lower()" with "mw.ustring.lower(val)" in the
-- following line.
val = type(val) == 'string' and val:lower() or val
if val == nil then
return nil
elseif val == true
or val == 'yes'
or val == 'y'
or val == 'true'
or val == 't'
or val == 'да'
or val == 'д'
-- кириллица
or val == 'у'
or val == '+'
or tonumber(val) == 1
then
return true
elseif val == false
or val == 'no'
or val == 'n'
or val == 'false'
or val == 'f'
or val == 'нет'
or val == 'н'
or val == '-'
or tonumber(val) == 0
then
return false
else
return default
end
end
ae94e12a838e770797317ed07b57b330ffeb7658
Шаблон:Yesno-yes
10
66
129
2024-04-05T13:04:36Z
wikipedia:ru>Stjn
0
подстановка
wikitext
text/x-wiki
{{safesubst:<noinclude />yesno|{{{1}}}|yes={{{yes|yes}}}|no={{{no|no}}}|blank={{{blank|yes}}}|¬={{{¬|yes}}}|def={{{def|yes}}}}}<noinclude>
{{doc}}
</noinclude>
3792ff694708f98102e3a6d556abe73bedc29069
Шаблон:Выполнить скрипт
10
100
197
2024-04-07T13:34:28Z
wikipedia:ru>Stjn
0
отключение старой схемы
wikitext
text/x-wiki
{{#switch: {{{1|}}}
| =
| mainPage = [[Категория:Википедия:Заглавная страница|{{NAMESPACENUMBER}}]]
| #default = {{#ifexist: Категория:Википедия:Страницы с гаджетом по требованию {{{1}}} | [[Категория:Википедия:Страницы с гаджетом по требованию {{{1}}}|{{NAMESPACENUMBER}}]] }}
}}<noinclude>
{{doc}}
</noinclude>
6979ea0342067dc76b9adcb9a5e072207c2c5a63
Шаблон:Старый-новый стиль,примечание
10
104
205
2024-04-13T19:25:38Z
wikipedia:ru>Mikhail Ryazanov
0
[[Календарная дата#Форматы записи даты]], стилевые правки
wikitext
text/x-wiki
В случае, если дата рождения/смерти в источниках приведена по [[Юлианский календарь|старому стилю]], рекомендуется указывать её по новому стилю, а после указать в скобках отличающуюся часть даты по старому стилю. Например,
* «13.05.1801 (1)» будет отображено как [[13 мая|1 (13) мая]] [[1801 год|1801]];
* «12.06.1801 (31.05)» будет отображено как 31 мая ([[12 июня]]) [[1801 год|1801]];
* «12.01.1802 (31.12.1801)» будет отображено как 31 декабря 1801 ([[12 января]] [[1802 год|1802]]).
При этом в статью будут автоматически подставлены категории даты рождения/смерти по ''новому'' стилю. Учтите, что разница между датами нового и старого стиля составляет 13 дней в XX и XXI веках, 12 дней в XIX веке, 11 дней в XVIII веке, 10 дней в XVII и XVI веках (начиная с 5 (15) октября 1582 года).<noinclude>{{doc-inline}}Шаблон предназначен для подстановки в качестве примечания к полям «дата рождения», «дата смерти» для страниц документации шаблонов-карточек типа «Персона».
Параметров не принимает.
Вызов: {{tl|Старый-новый стиль,примечание}} {{doc-end}} [[Категория:Википедия:Шаблоны, встраиваемые в шаблоны-карточки:Личности]]
</noinclude>
7f8754eb5c2401671df545a1cd8b315f66f86463
Шаблон:Replace
10
37
71
2024-04-14T07:24:11Z
wikipedia:ru>Stjn
0
обновление аналогично английскому шаблону
wikitext
text/x-wiki
{{safesubst:<noinclude />#invoke:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|plain={{{plain|true}}}|count={{{count|}}}}}<noinclude>
{{doc}}
</noinclude>
7752c3c70ae8c46a89a0808aa282956866dbba5b
Шаблон:Wikidata gender switch
10
49
95
2024-04-28T17:08:48Z
wikipedia:ru>Dima st bk
0
+ lc по запросу на СО
wikitext
text/x-wiki
{{#switch: {{wikidata|p21|{{lc:{{delink|{{{1|}}}}}}}|plain=true|from={{{from|}}}}}
| 1 | f | fem | female | feminine | ж | жен | женский | женский пол | транс-женщина | Q6581072 | Q1052281 | Q43445 = {{{2}}}
| m | male | masculine | м | муж | мужской | мужской пол | транс-мужчина | Q6581097 | Q2449503 | Q44148 = {{{3}}}
| #default = {{#if:{{{4|}}}|{{{4}}}|{{{3}}}}}
}}<noinclude>
{{doc}}
</noinclude>
24ccdd5a8702a7028386e9b887d3acf1b5f81c34
Шаблон:Действия для страницы/styles.css
10
86
169
2024-05-02T17:22:30Z
wikipedia:ru>Stjn
0
fix
text
text/plain
.ts-tlinks-tlinks {
font-weight: normal;
float: right;
line-height: inherit;
}
.ts-tlinks-tlinks .mw-editsection-divider {
display: inline;
}
/* [[Категория:Шаблоны:Подстраницы CSS]] */
a003e896d263c29e66d2246b210e5d73e577ea46
Шаблон:Действия для страницы
10
85
167
2024-05-02T17:24:27Z
wikipedia:ru>Stjn
0
никаких пиксельных fontsize
wikitext
text/x-wiki
<templatestyles src="Шаблон:Действия для страницы/styles.css" /><div style="{{#ifeq: {{yesno-yes|{{{right|}}}}} | yes || float:none; }}" class="ts-tlinks-tlinks mw-editsection-like plainlinks"><span class="mw-editsection-bracket">[</span><!--
-->{{join|separator=<span class="mw-editsection-divider"> &#124; </span>
|1={{#ifexist: {{#rel2abs: {{{lc|}}} }}
| {{#ifeq: {{{dislooklink|{{{noview|}}}}}} | yes || [[{{{lc}}}|просмотр]] }}
}}
|2={{#ifexist: {{#rel2abs: {{{lc|}}} }}
| [[Special:EditPage/{{#rel2abs: {{{lc}}} }}|править]]
}}
|3={{#ifexist: {{#rel2abs: {{{lc|}}} }}
| {{#ifeq: {{{dishistlink|{{{nohistory|}}}}}} | yes || [[Special:PageHistory/{{#rel2abs: {{{lc}}} }}|история]] }}
}}
|4={{#ifexist: {{#rel2abs: {{{lc|}}} }}
|
| [{{fullurl:{{#rel2abs: {{{lc}}} }}|action=edit&redlink=1}} создать]
}}
|5={{#ifeq: {{{diswatchlink|{{{nowatch|}}}}}} | yes || [{{fullurl:{{#rel2abs: {{{lc}}} }}|action=watch}} следить] }}
|6={{#ifeq: {{{disupdlink|{{{noupdate|}}}}}} | yes || {{очистить кэш|обновить|nocat=1}}</span> }}
}}<span class="mw-editsection-bracket">]</span></div><noinclude>
{{doc}}
</noinclude>
9ee2c9eed92e2ecc9377a7b9486ad8bc214a83d4
Модуль:Wikidata/Medals
828
68
133
2024-05-04T17:24:40Z
wikipedia:ru>Putnik
0
импорт списка дубликатов из [[az:Modul:Wikidata/Medals]]
Scribunto
text/plain
local WDS = require( 'Module:WikidataSelectors' )
local moduleDate = require( 'Module:Wikidata/date' )
local awardsOrder = mw.ext.data.get( "Wikidata/awards order.tab" )
local p = {}
local config = {
--Hide award with key QID if there is a reward with value QID
absorption = {
Q16675272 = 'Q654471',
Q16481808 = 'Q8706404',
Q1948730 = 'Q178473',
Q1980962 = 'Q208167',
Q2032399 = 'Q2046996',
Q102183407 = 'Q103819965',
Q1262166 = 'Q80589',
Q749849 = 'Q1358055',
Q4287121 = 'Q4137462',
}
}
--Get string with dates from qualifiers table
local function datesFromQualifier( context, options, qualifierId )
local dates = {}
local qualifiers = options.qualifiers[ qualifierId ]
if qualifiers then
for _, qualifier in pairs( qualifiers ) do
if qualifier.datavalue then
local dateValue = moduleDate.formatDate( context, options, qualifier.datavalue.value )
if dateValue then
table.insert( dates, dateValue )
end
end
end
end
return table.concat( dates, ', ' )
end
--Property function for [[d:Property:P166]]
function p.formatProperty( context, options )
if ( not context ) then error( 'context not specified' ); end;
if ( not options ) then error( 'options not specified' ); end;
if ( not options.entityId ) then error( 'options.entityId missing' ); end;
local claims;
if options.property then -- TODO: Почему тут может не быть property?
claims = context.selectClaims( options, options.property );
end
if claims == nil then
return '' --TODO error?
end
-- Обход всех заявлений утверждения и с накоплением оформленых
-- предпочтительных заявлений в таблице.
local formattedData = {}
for i, claim in ipairs( claims ) do
if ( claim.mainsnak and
claim.mainsnak and
claim.mainsnak.datavalue and
claim.mainsnak.datavalue.type == 'wikibase-entityid'
) then
local valueId = claim.mainsnak.datavalue.value.id
local formattedStatement = context.formatStatement( options, claim )
-- здесь может вернуться либо оформленный текст заявления, либо строка ошибки, либо nil
if ( formattedStatement and formattedStatement ~= '' ) then
formattedStatement = '<span class="wikidata-claim" data-wikidata-property-id="' .. string.upper( options.property ) .. '" data-wikidata-claim-id="' .. claim.id .. '">' .. formattedStatement .. '</span>'
table.insert( formattedData, {
id = valueId,
html = formattedStatement,
} )
end
end
end
-- Удаление дублей (медаль + звание -> звание)
for i, awardData in ipairs( formattedData ) do
local isAbsorptionFound = false
if config.absorption[ awardData.id ] then
local absorptionAwardId = config.absorption[ awardData.id ]
for _, absorptionAwardData in ipairs( formattedData ) do
if absorptionAwardData.id == absorptionAwardId then
isAbsorptionFound = true
break
end
end
end
if isAbsorptionFound then
table.remove( formattedData, i )
end
end
-- Сортировка медалей по старшинству
local orderedData = {}
local lastValue;
if ( type (awardsOrder) == 'table' ) then
-- Если не отсохла stuctured data
for i, awardFields in ipairs( awardsOrder.data ) do
local awardOrder = awardFields[ 1 ]
if awardOrder == '-' then
-- separator
if lastValue ~= '-' then
table.insert( orderedData, '<br>' )
lastHeight = nil
end
else
for k, awardData in ipairs( formattedData ) do
if awardOrder == awardData.id and not awardData.used then
table.insert( orderedData, awardData.html )
formattedData[ k ].used = true
end
end
end
end
end
for i, awardData in ipairs( formattedData ) do
if not awardData.used then
table.insert( orderedData, awardData.html )
end
end
local lastHeight
for i, awardHtml in ipairs( orderedData ) do
local height = mw.ustring.match( awardHtml, 'x%d+px' )
if height and lastHeight and height ~= lastHeight then
table.insert( orderedData, i, '<br>' )
end
lastHeight = height
end
-- создание текстовой строки со списком оформленых заявлений из таблицы
local out = mw.text.listToText( orderedData, options.separator, options.conjunction )
if out ~= '' then
if options.before then
out = options.before .. out
end
if options.after then
out = out .. options.after
end
end
return out
end
local function getImageFromProperty( entityId, propertyId )
local imageClaims = WDS.load( entityId, propertyId )
if imageClaims and #imageClaims > 0 then
for _, claim in ipairs( imageClaims ) do
if claim.type == 'statement' and claim.mainsnak.snaktype == 'value' then
return claim.mainsnak.datavalue.value
end
end
end
return nil
end
-- Получение изображения (планки или иконки) и его размера
function p.getImageFromEntity( entityId, actualDate )
if type( entityId ) ~= "string" then
entityId = entityId.id
end
local image = nil
local size = 'x17px'
local border = false
-- получение изображения планки из элемента
image = getImageFromProperty( entityId, 'P2425' )
if image then
border = true
end
-- получение иконки из элемента
if not image then
image = getImageFromProperty( entityId, 'P2910' )
if image then
size = '40x40px'
end
end
return image, size, border
end
--Value function for [[d:Property:P166]]
function p.formatValue( context, options, statement )
local entityId = statement.id
if not entityId then
return statement
end
local label = mw.wikibase.getLabel( entityId )
local image, size, border = p.getImageFromEntity( entityId )
local recipientCategory = ''
if not options.nocat and options.nocat ~= '' then
recipientCategory = context.extractCategory( { category = 'P7084[P4224:Q24571879]' }, entityId )
if recipientCategory == '' then
recipientCategory = context.extractCategory( { category = 'P2517' }, entityId )
end
end
local dates = ''
if options.qualifiers then
local startDates = {}
dates = datesFromQualifier( context, options, 'P580' )
if dates ~= '' then
local endDates = datesFromQualifier( context, options, 'P582' )
if endDates and endDates ~= '' then
dates = dates .. ' — ' .. endDates
end
else
dates = datesFromQualifier( context, options, 'P585' )
end
if options.qualifiers.P27 then
mw.log('>>>>>>>>>>>>>')
for _, claim in ipairs( options.qualifiers.P27 ) do
if claim and claim.datavalue and claim.datavalue.value and claim.datavalue.value.id then
local categoryOptions = { category = 'P7084[P27:' .. claim.datavalue.value.id .. ']' }
recipientCategory = recipientCategory .. context.extractCategory( categoryOptions, entityId )
end
end
end
end
-- получение ссылки по идентификатору и вывод планки
if image then
local link = mw.wikibase.getSitelink( entityId )
local out = '[[File:' .. image
if border == true then
out = out .. '|border'
end
out = out .. '|' .. size .. '|link='
-- получение ссылки из родительского элемента
-- для степеней обычно только одна общая статья
if not link then
local partOfClaims = WDS.load( entityId, 'P361' ) -- часть от
if not partOfClaims or #partOfClaims == 0 then
partOfClaims = WDS.load( entityId, 'P279' ) -- подкласс от
end
if partOfClaims and #partOfClaims > 0 then
for _, claim in ipairs( partOfClaims ) do
if claim.type == 'statement' and claim.mainsnak.snaktype == 'value' then
link = mw.wikibase.getSitelink( claim.mainsnak.datavalue.value.id )
if link then
break
end
end
end
end
end
if link then
out = out .. link
else
out = out .. 'd:' .. entityId
end
if label then
out = out .. '|' .. label
end
out = out .. ']]'
out = out .. recipientCategory
return out
end
local out = context.formatValueDefault( context, options, statement )
if out and out ~= '' then
if dates ~= '' then
out = out .. ' (' .. dates .. ')'
end
return '<span style="display:inline-block; text-align:left>' .. out .. recipientCategory .. '</span>'
end
return ''
end
--Table for documentation
function p.renderDoc()
local out = {}
for i, awardFields in ipairs( awardsOrder.data ) do
local awardId = awardFields[ 1 ]
local link = '[[d:' .. awardId .. '|' .. awardId .. ']]'
if i == 351 then
-- limits
table.insert( out, '| … || … || … || … || …' )
elseif i > 351 and i < #awardsOrder.data then
-- do nothing
elseif awardId == '-' then
-- separator
table.insert( out, '|' .. i .. '|| colspan="3" | ----' )
else
local image, size, border = p.getImageFromEntity( awardId )
if image then
image = '[[File:' .. image
if border == true then
image = image .. '|border'
end
image = image .. '|' .. size .. ']]'
else
image = ''
end
local label = mw.wikibase.getLabel( awardId ) or ''
local article = mw.wikibase.getSitelink( awardId )
if article then
if label == '' then
label = article
end
label = '[[' .. article .. '|' .. label .. ']]'
end
local countryStatements = mw.wikibase.getBestStatements( awardId, 'P17' )
local countries = {}
if countryStatements then
for _, statement in ipairs( countryStatements ) do
if statement.mainsnak.datavalue and
statement.mainsnak.datavalue.type == 'wikibase-entityid'
then
local countryId = statement.mainsnak.datavalue.value.id
table.insert( countries, mw.wikibase.getLabel( countryId ) )
end
end
end
table.insert( out, '|' .. i .. '||' .. link .. '||' .. image ..
'||' .. label .. '||' .. table.concat( countries, ', ' ) )
end
end
return '{| class="wikitable"\n' ..
'! # !! Элемент !! Планка !! Название !! Государство\n|-\n' ..
table.concat( out, '\n|-\n' ) ..
'\n|}'
end
return p
4de64e0e2181e8a4487f3e18da893fca9f92660d
Шаблон:OnLua
10
98
193
2024-05-07T19:08:37Z
wikipedia:ru>MBH
0
MBH переименовал страницу [[Шаблон:OnLua]] в [[Шаблон:Lua]]
wikitext
text/x-wiki
#перенаправление [[Шаблон:Lua]]
b72371e7ae22239863c474a78238171c2bd94c7e
Шаблон:Lua
10
105
207
2024-05-07T19:08:37Z
wikipedia:ru>MBH
0
MBH переименовал страницу [[Шаблон:OnLua]] в [[Шаблон:Lua]]
wikitext
text/x-wiki
<includeonly>{{ombox
| small = yes
| style = width:23em;
| image = [[Файл:Lua-logo-nolabel.svg|40px|alt=|link=]]
| text = {{replace|Этот шаблон {{#if: {{{partly|}}} | частично }} реализован на основе [[Lua]]{{#if:{{{module2|}}}{{{tech2|}}}|:<br><ul><li>}}{{#if:{{{1|}}}{{{tech|}}}| с использованием {{{tech|{{#if:{{{2|}}}|функции <code>{{#if:{{{line|}}}|[[Module:{{{1}}}#L-{{{line}}}|{{{2}}}()]]|[[{{{funcref|Module:{{{1}}}#{{{2}}}}}}|{{{2}}}()]]}}</code> из }}{{#if:{{{1|}}}|модуля [[Module:{{{1}}}|{{{1}}}]]}}}}};}}<!--
-->{{#invoke:Transclude|npc|OnLua/Строка|
module=
|function=
|tech=
|line=
}}.|;.|.}}{{#if:{{{module2|}}}{{{tech2|}}}|</ul>}} {{#if:{{{1|}}}{{{tech|}}}{{{module1|}}}{{{tech1|}}}||<div class="error"><small>'''Не указано название использующегося модуля!'''</small></div>}}
}}{{#ifeq:{{SUBPAGENAME}}|{{{doc|doc}}}||{{#if:{{{nocat|}}}||[[Категория:Шаблоны, использующие Scribunto]]{{#if:{{{1|}}}{{{tech|}}}{{{module1|}}}{{{tech1|}}}||[[Категория:Шаблоны, использующие Lua, без указания модуля]]}}}}}}</includeonly><noinclude>{{doc}}</noinclude>
f1fdaa87edb15d61e23e98f6e25d171a975e10eb
Шаблон:OnLua/Строка
10
101
199
2024-05-07T19:08:38Z
wikipedia:ru>MBH
0
MBH переименовал страницу [[Шаблон:OnLua/Строка]] в [[Шаблон:Lua/Строка]]
wikitext
text/x-wiki
#перенаправление [[Шаблон:Lua/Строка]]
d7f869ccc7a7efc800399fce32bc75e0f91066de
Шаблон:Lua/Строка
10
112
221
2024-05-07T19:08:38Z
wikipedia:ru>MBH
0
MBH переименовал страницу [[Шаблон:OnLua/Строка]] в [[Шаблон:Lua/Строка]]
wikitext
text/x-wiki
<includeonly>{{#if: {{{module|}}}{{{tech|}}} | <li>с использованием {{#if: {{{tech|}}} | {{{tech}}} | {{#if: {{{function|}}} | {{#if: {{{module|}}} | функции <code>{{#if: {{{line|}}} | [{{fullurl: Module:{{{module}}}|action=edit}}#mw-ce-l{{{line}}} {{{function}}}()] | [[{{{funcref|Module:{{{module}}}#{{{function}}}}}} | {{{function}}}()]]}}</code> из }}}}{{#if: {{{module|}}} | модуля [[Module:{{{module}}} | {{{module}}}]]}}}};}}</includeonly><noinclude>[[Категория:Шаблоны:Подстраницы шаблонов]]</noinclude>
5a35837338c2daee2d240a8e5335e8fec8e7d87e
Шаблон:Wikidata/p569
10
46
89
2024-05-08T19:10:13Z
wikipedia:ru>Dima st bk
0
|suppressAge={{{suppress age|}}} с викиданных
wikitext
text/x-wiki
{{#switch:{{{1|}}}|-=|={{#invoke:Wikidata|formatStatements|property=p569|claim-module=Wikidata/date|claim-function=formatDateOfBirthClaim|nocat={{{nocat|}}}{{NAMESPACE}}|suppressAge={{{suppress age|}}}}}|{{#invoke:Infocards|dateOfBirth|{{{1|}}}|{{{2|}}}|suppressAge={{wikidata|P570|plain=true}}{{{suppress age|}}}|nocat={{{nocat|}}}{{NAMESPACE}}}}}}<noinclude>{{doc}}</noinclude>
9643ab18fcd322831b72e38658b58c6b94a914e2
Шаблон:Установлена проверка на неизвестные параметры
10
95
187
2024-05-10T14:11:21Z
wikipedia:ru>Abiyoyo
0
категория для шаблонов отдельно, для самих категорий отдельно
wikitext
text/x-wiki
{{ombox
|name = Установлена проверка на неизвестные параметры
|text = В этом шаблоне установлена [[Модуль:Check for unknown parameters|проверка на неизвестные параметры]], добавляющая страницы в {{c|{{#if:{{{категория|}}}|{{{категория|}}}|Страницы с неизвестными параметрами шаблона {{ROOTPAGENAME}}}}|В}}.
|type = notice
}}<includeonly>{{no-doc|[[Категория:Шаблоны с установленной проверкой на неизвестные параметры]]{{#ifexist: Категория:{{#if:{{{категория|}}}|{{{категория|}}}|Страницы с неизвестными параметрами шаблона {{ROOTPAGENAME}}}} || [[Категория:Шаблоны с установленной проверкой на неизвестные параметры и несуществующей категорией]] }}|nocat={{{nocat|}}}}}</includeonly><noinclude>{{doc-inline}}
См. [[Модуль:Check for unknown parameters]] и [[:Категория:Википедия:Неизвестные параметры шаблонов]].
Добавляет {{Категория с размером|Шаблоны с установленной проверкой на неизвестные параметры и несуществующей категорией}}.
[[Категория:Шаблоны:Предупреждения]]
[[Категория:Шаблоны:Для документирования шаблонов]]
{{doc-end}}
</noinclude>
cd47e06eec53b65393adba1f3143d6cd3d6cc54c
Модуль:Wikidata/date
828
59
115
2024-06-10T15:24:01Z
wikipedia:ru>Stjn
0
необъявленная глобальная переменная
Scribunto
text/plain
--settings
local nowLabel = 'наст. время'
local moduleDates = require( "Module:Dates" )
local moduleWikidata = require( "Module:Wikidata" )
local dateCat = require("Module:Infocards/dateCat")
-- FIXME: undeclared global variable, used 3 times
local infoclass
local function deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
setmetatable(copy, deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
local function ageImpl ( bStructure, bPrecision, dStructure, dPrecision )
if ( not bStructure or not dStructure or bPrecision < 10 or dPrecision < 10 ) then
return nil
end
local shift = 0
if ( bStructure.year < 0 and dStructure.year > 0 ) then
shift = -1
end
if ( bPrecision == 10 or dPrecision == 10 ) then
if ( bStructure.month < dStructure.month ) then
return dStructure.year - bStructure.year + shift
end
if ( bStructure.month == dStructure.month ) then
return nil
end
if ( bStructure.month > dStructure.month ) then
return dStructure.year - bStructure.year - 1 + shift
end
end
if ( bStructure.month < dStructure.month ) then
return dStructure.year - bStructure.year + shift
end
if ( bStructure.month == dStructure.month ) then
if ( bStructure.day <= dStructure.day ) then
return dStructure.year - bStructure.year + shift
else
return dStructure.year - bStructure.year - 1 + shift
end
end
if ( bStructure.month > dStructure.month ) then
return dStructure.year - bStructure.year - 1 + shift
end
return nil
end
-- accepts table of time+precision values
local function ageCurrent ( bTable )
local possibleAge = "NYA" -- it means "Not Yet Assigned", not what you imagined!
for bKey, bValue in pairs(bTable) do
if ( bValue.unknown ) then
return nil
end
local bStructure = bValue.structure
local bPrecision = bValue.precision
local dStructure = os.date( "*t" )
local calculatedAge = ageImpl ( bStructure, bPrecision, dStructure, 11 )
if ( possibleAge == "NYA" ) then
possibleAge = calculatedAge
else
if ( possibleAge ~= calculatedAge ) then
possibleAge = nil
end
end
end
return possibleAge
end
-- accepts tables of time+precision values
local function age ( bTable, dTable )
local possibleAge = "NYA" -- it means "Not Yet Assigned", not what you imagined!
for bKey, bValue in pairs( bTable ) do
if ( bValue.unknown ) then
return nil
end
local bStructure = bValue.structure
local bPrecision = bValue.precision
for dKey, dValue in pairs( dTable ) do
if ( dValue.unknown ) then
return nil
end
local dStructure = dValue.structure
local dPrecision = dValue.precision
if ( bValue.calendar == 'julian' and dValue.calendar == 'gregorian' ) then
-- to calculate age, need to adjust bStructure to gregorian calendar
local shift = math.floor(bStructure.year/100-2) - math.floor(bStructure.year/400)
-- TODO: re-implement this properly
bStructure.day = bStructure.day + shift
end
local calculatedAge = ageImpl ( bStructure, bPrecision, dStructure, dPrecision )
if ( possibleAge == "NYA" ) then
possibleAge = calculatedAge
else
if ( possibleAge ~= calculatedAge ) then
possibleAge = nil
end
end
end
end
return possibleAge
end
local function parseISO8601Date(str)
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local Y, M, D = mw.ustring.match( str, pattern )
return tonumber(Y), tonumber(M), tonumber(D)
end
local function parseISO8601Time(str)
local pattern = "T(%d+):(%d+):(%d+)%Z"
local H, M, S = mw.ustring.match( str, pattern)
return tonumber(H), tonumber(M), tonumber(S)
end
local function parseISO8601Offset(str)
if str:sub(-1)=="Z" then return 0,0 end -- ends with Z, Zulu time
-- matches ±hh:mm, ±hhmm or ±hh; else returns nils
local pattern = "([-+])(%d%d):?(%d?%d?)$"
local sign, oh, om = mw.ustring.match( str, pattern)
sign, oh, om = sign or "+", oh or "00", om or "00"
return tonumber(sign .. oh), tonumber(sign .. om)
end
local function parseISO8601(str)
if 'table' == type(str) then
if str.args and str.args[1] then
str = '' .. str.args[1]
else
return 'unknown argument type: ' .. type( str ) .. ': ' .. table.tostring( str )
end
end
local Y,M,D = parseISO8601Date(str)
local h,m,s = parseISO8601Time(str)
local oh,om = parseISO8601Offset(str)
if not Y or not M or not D or not h or not m or not s or not oh or not om then
return nil
end
return tonumber(os.time({year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s}))
end
local function parseClaim ( claim )
if ( claim.mainsnak.snaktype == "value" ) then
local timeISO8601 = string.gsub( string.gsub( tostring( claim.mainsnak.datavalue.value.time ), '-00%-', '-01-' ), '-00T', '-01T' )
local unixtime = parseISO8601( timeISO8601 )
local structure = os.date("*t", unixtime)
local precision = tonumber( claim.mainsnak.datavalue.value.precision )
local calendarmodel = 'gregorian'
if (mw.ustring.find(claim.mainsnak.datavalue.value.calendarmodel, 'Q1985786', 1, true)) then
calendarmodel = 'julian'
end
local item = { structure=structure, precision=precision, calendar = calendarmodel }
return item
elseif ( claim.mainsnak.snaktype == "novalue" ) then
-- novalue
return { unknown="novalue" }
else
--unknown
return { unknown="unknown" }
end
end
-- returns table of time+precision values for specified property
local function parseProperty ( context, options, propertyId )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not options.entity ) then error( 'options.entity is missing'); end
if ( not propertyId ) then error( 'propertyId not specified'); end
local claims = context.selectClaims( options, propertyId )
if not claims then
return nil
end
local result = {}
for key, claim in pairs( claims ) do
table.insert ( result, parseClaim( claim ) )
end
return result
end
-- проверка на совпадающие даты с разной моделью календаря
local function checkDupDates( t )
if #t > 1 then
local removed = false
local j = 1
-- проверка на совпадающие даты с разной моделью календаря
while (j <= #t) do
local i = 1
while (i <= #t) do
if i ~= j then
if (os.time(t[j].structure) == os.time(t[i].structure)) then
if ((t[j].calendarmodel == 'gregorian') and
(t[i].calendarmodel == 'julian')) then
removed = true
break
else
table.remove(t, i)
end
else
i = i + 1
end
else
i = i + 1
end
end
if removed then
removed = false
table.remove(t, j)
else
j = j+1
end
end
end
end
-- returns first qualifier of specified propertyId
local function getQualifierWithDataValue( statement, qualifierPropertyId )
if ( statement.qualifiers
and statement.qualifiers[qualifierPropertyId] ) then
local qualifiers = statement.qualifiers[qualifierPropertyId]
for _, qualifier in ipairs( qualifiers ) do
if (qualifier.datavalue) then
return qualifier
end
end
end
return nil
end
local p = {}
local function formatDecade( time, categoryNamePrefix )
local bce = ''
local year
if time.year < 0 then
bce = ' до н. э.'
year = math.floor( math.abs( time.year ) / 10 ) * 10
else
year = math.floor( time.year / 10 ) * 10
end
local unit = '-е'
if isGenitive then
unit = '-х'
end
local value = '' .. year .. unit .. bce
if categoryNamePrefix then
return value .. '[[Category:' .. categoryNamePrefix .. ' в ' .. year .. '-е годы' .. bce .. ']]'
end
return value
end
local function formatCentury( time, categoryNamePrefix, isGenitive )
local moduleRoman = require( 'Module:RomanNumber' )
local bce = ''
local century
if time.year < 0 then
bce = ' до н. э.'
century = math.floor( ( math.abs( time.year ) - 1 ) / 100 ) + 1
else
century = math.floor( ( time.year - 1 ) / 100 ) + 1
end
local unit = 'век'
if isGenitive then
unit = 'века'
end
local infix = ' в '
if century == 2 then
infix = ' во '
end
if moduleRoman then
century = moduleRoman.toRomanNumber( century )
end
local value = '[[' .. century .. ' век' .. bce .. '|' .. century .. ' ' .. unit .. bce .. ']]'
if categoryNamePrefix then
return value .. '[[Category:' .. categoryNamePrefix .. infix .. century .. ' веке' .. bce .. ']]'
end
return value
end
local function formatMillenium( time, categoryNamePrefix, isGenitive )
local bce = ''
local millenium
if time.year < 0 then
bce = ' до н. э.'
millenium = math.floor( ( math.abs( time.year ) - 1 ) / 1000 ) + 1
else
millenium = math.floor( ( time.year - 1 ) / 1000 ) + 1
end
local unit = '-е тысячелетие'
if isGenitive then
unit = '-го тысячелетия'
end
local value = '[[' .. millenium .. '-е тысячелетие' .. bce .. '|' .. millenium .. unit .. bce .. ']]'
if categoryNamePrefix then
local infix = ' в '
if millenium == 2 then
infix = ' во '
end
return value .. '[[Category:' .. categoryNamePrefix .. infix .. millenium .. '-м тысячелетии' .. bce .. ']]'
else
return value
end
end
local function formatDateImpl( value, options, microformatClass, categoryPrefix, leftBracket, rightBracket, nolinks, isGenitive )
if ( not value ) then error( 'value not specified'); end
if ( not options ) then error( 'options not specified'); end
-- The calendar model used for saving the data is always the proleptic Gregorian calendar according to ISO 8601.
local timeISO8601 = string.gsub( string.gsub( tostring( value.time ), '-00%-', '-01-' ), '-00T', '-01T' )
local unixtime = parseISO8601( timeISO8601 )
if not unixtime then
return ''
end
local structure = os.date("*t", unixtime)
local precision = tonumber( value.precision )
if precision <= 6 then
return formatMillenium( structure, categoryPrefix, isGenitive )
end
if precision == 7 then
return formatCentury( structure, categoryPrefix, isGenitive )
end
if precision == 8 then
return formatDecade( structure, categoryPrefix, isGenitive )
end
if precision == 9 then
local tCopy = deepcopy( structure )
tCopy.day = nil
tCopy.month = nil
return moduleDates.formatWikiImpl( tCopy, tCopy, infoclass, categoryPrefix, leftBracket, rightBracket, nolinks )
end
-- year and month only
if precision == 10 then
local tCopy = deepcopy( structure )
tCopy.day = nil
return moduleDates.formatWikiImpl( tCopy, tCopy, infoclass, categoryPrefix, leftBracket, rightBracket, nolinks )
end
local calendarmodel = 'gregorian'
if (mw.ustring.find(value.calendarmodel, 'Q1985786', 1, true)) then
calendarmodel = 'julian'
end
if (calendarmodel == 'gregorian') then
return moduleDates.formatWikiImpl( structure, structure, microformatClass, categoryPrefix, leftBracket, rightBracket, nolinks )
else
return p.formatAsJulian( timeISO8601, infoclass, categoryPrefix, leftBracket, rightBracket, nolinks )
end
end
local function formatApproximateDateClaim( context, options, statement, unknownDateCategory )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not options.entity ) then error( 'options.entity is missing'); end
if ( not statement ) then error( 'statement not specified'); end
if options.nocat then unknownDateCategory = "" end
local qNotSoonerThan = getQualifierWithDataValue( statement, 'P1319' )
local qNotLaterThan = getQualifierWithDataValue( statement, 'P1326' )
if ( qNotSoonerThan or qNotLaterThan ) then
local results = {}
if ( qNotSoonerThan ) then
local formattedDate = formatDateImpl( qNotSoonerThan.datavalue.value, {}, nil, nil, options.leftBracket, options.rightBracket, options.nolinks, true )
local value = 'не ранее ' .. context.wrapSnak( formattedDate, qNotSoonerThan.hash )
table.insert( results, context.wrapQualifier( value, 'P1319' ) )
end
if ( qNotLaterThan ) then
local formattedDate = formatDateImpl( qNotLaterThan.datavalue.value, {}, nil, nil, options.leftBracket, options.rightBracket, options.nolinks, true )
local value = 'не позднее ' .. context.wrapSnak( formattedDate, qNotLaterThan.hash )
table.insert( results, context.wrapQualifier( value, 'P1326' ) )
end
return mw.text.listToText( results, ' и ' , ' и ' ) .. unknownDateCategory .. context.formatRefs( options, statement )
end
return nil
end
function p.formatDateOfBirthClaim( context, options, statement )
local value = formatApproximateDateClaim( context, options, statement, dateCat.categoryUnknownBirthDate )
if value then
return value
end
options['conjunction'] = ' или '
options['value-module'] = 'Wikidata/date'
options['value-function'] = 'formatBirthDate'
options.i18n.somevalue = '\'\'неизвестно\'\'' .. dateCat.categoryUnknownBirthDate
local circumstances = context.getSourcingCircumstances( statement )
for _, itemId in ipairs( circumstances ) do
if itemId == 'Q5727902' then
options.isGenitive = true
break
end
end
local result = context.formatStatementDefault( context, options, statement )
local bTable = { parseClaim( statement ) }
local dTable = parseProperty ( context, options, 'P570' )
if ( bTable and not dTable ) then
local age = ageCurrent( bTable )
if ( age ) then
if ( options.suppressAge == nil or options.suppressAge == '' ) then
result = result .. ' <span style="white-space:nowrap;">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>'
end
if ( not options.nocat ) then
if ( age > 115 ) then
result = result .. dateCat.categoryBigCurrentAge
elseif (age >= 0) then
result = result .. dateCat.categoryBiographiesOfLivingPersons
else
result = result .. dateCat.categoryNegativeAge
end
end
end
end
return result
end
function p.formatDateOfDeathClaim( context, options, statement )
local value = formatApproximateDateClaim( context, options, statement, dateCat.categoryUnknownDeathDate )
if value then
return value
end
options['conjunction'] = ' или '
options['value-module'] = 'Wikidata/date'
options['value-function'] = 'formatDeathDate'
options.i18n.somevalue = '\'\'неизвестно\'\'' .. dateCat.categoryUnknownDeathDate
local circumstances = context.getSourcingCircumstances( statement )
for _, itemId in ipairs( circumstances ) do
if itemId == 'Q5727902' then
options.isGenitive = true
break
end
end
local result = context.formatStatementDefault( context, options, statement )
local bTable = parseProperty ( context, options, 'P569' )
local dTable = { parseClaim( statement ) }
if ( bTable and dTable ) then
local age = age( bTable, dTable )
if ( age ) then
if ( options.suppressAge == nil or options.suppressAge == '' ) then
result = result .. ' <span style="white-space:nowrap;">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>'
end
if ( not options.nocat and age < 0) then
result = result .. dateCat.categoryNegativeAge
end
end
-- returns category to recently deceased persons
local unixAvailable, unixDateOfDeath = pcall(function()
local r = os.time(dTable[1].structure)
if ( r ~= os.time() ) then
return r
end
error()
end)
if ( unixAvailable and os.time() - unixDateOfDeath < 31536000 and not options.nocat ) then
result = result .. dateCat.categoryRecentlyDeceased
end
end
return result
end
-- Reentry point for Wikidata Snak formatting
function p.formatBirthDate( context, options, value )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not value ) then error( 'value not specified'); end
local microformatClass = nil
if options.microformat ~= '-' then
microformatClass = options.microformat or 'bday'
end
if ( options.nocat ) then
return formatDateImpl( value, options, microformatClass, nil, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
else
return formatDateImpl( value, options, microformatClass, 'Родившиеся', options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
end
end
-- Reentry point for Wikidata Snak formatting
function p.formatDeathDate( context, options, value )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not value ) then error( 'value not specified'); end
local microformatClass = nil
if options.microformat ~= '-' then
microformatClass = options.microformat or 'dday'
end
if ( options.nocat and options.nocat ~= '' ) then
return formatDateImpl( value, options, microformatClass, nil, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
else
return formatDateImpl( value, options, microformatClass, 'Умершие', options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
end
end
-- Reentry point for Wikidata Snak formatting -- default one
function p.formatDate( context, options, value )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not value ) then error( 'value not specified'); end
local microformatClass = options.microformat or nil
if ( options.nocat and options.nocat ~= '' ) then
return formatDateImpl( value, options, microformatClass, nil, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
else
local categoryPrefix = options.categoryPrefix or nil
return formatDateImpl( value, options, microformatClass, categoryPrefix, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
end
end
function p.formatDateIntervalProperty( context, options )
if ( not context ) then error( 'context not specified' ); end
if ( not options ) then error( 'options not specified' ); end
if ( not options.entity ) then error( 'options.entity missing' ); end
-- Получение нужных утверждений
local WDS = require( 'Module:WikidataSelectors' )
local fromProperty = options.property
if options.from and options.from ~= '' then
fromProperty = options.from
end
local fromClaims = WDS.load( options.entityId, fromProperty )
local toClaims = WDS.load( options.entityId, options.to )
if fromClaims == nil and toClaims == nil then
return ''
end
local formattedFromClaims = {}
if fromClaims then
for i, claim in ipairs( fromClaims ) do
local formattedStatement = context.formatStatement( options, claim )
if formattedStatement then
formattedStatement = '<span class="wikidata-claim" data-wikidata-property-id="' .. string.upper( options.property ) .. '" data-wikidata-claim-id="' .. claim.id .. '">' .. formattedStatement .. '</span>'
table.insert( formattedFromClaims, formattedStatement )
end
end
end
local formattedToClaims = {}
local toOptions = deepcopy( options )
toOptions.property = options.to
toOptions.novalue = nowLabel
if toClaims then
for i, claim in ipairs( toClaims ) do
local formattedStatement = context.formatStatement( toOptions, claim )
if formattedStatement then
formattedStatement = '<span class="wikidata-claim" data-wikidata-property-id="' .. string.upper( toOptions.property ) .. '" data-wikidata-claim-id="' .. claim.id .. '">' .. formattedStatement .. '</span>'
table.insert( formattedToClaims, formattedStatement )
end
end
end
local out = ''
local fromOut = mw.text.listToText( formattedFromClaims, options.separator, options.conjunction )
local toOut = mw.text.listToText( formattedToClaims, options.separator, options.conjunction )
if fromOut ~= '' or toOut ~= '' then
if fromOut ~= '' then
out = fromOut
else
out = '?'
end
if toOut ~= '' then
out = out .. ' — ' .. toOut
else
local withinClaims = nil
if options.within then
WDS.load( options.entityId, options.within )
end
if withinClaims == nil then
out = 'с ' .. out
else
out = out .. ' — ' .. nowLabel
end
end
end
if out ~= '' then
if options.before then
out = options.before .. out
end
if options.after then
out = out .. options.after
end
end
return out
end
local lowestBoundary = '1582-10-05T00:00:00Z'
local lastBoundary = '1918-01-31T00:00:00Z'
local boundaries = {
-- from (G) till next will be diff(G = J + diff), at current
{ lowestBoundary, 10 },
{ '1700-02-29T00:00:00Z', 11 },
{ '1800-02-29T00:00:00Z', 12 },
{ '1900-02-29T00:00:00Z', 13 },
{ lastBoundary, '' },
}
-- Передаваемое время обязано быть по Юлианскому календарю (старому стилю)
function p.formatAsJulian( julTimeISO8601, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
if 'table' == type( julTimeISO8601 ) then
if julTimeISO8601.args and julTimeISO8601.args[1] then
julTimeISO8601 = julTimeISO8601.args[1]
else
return 'unknown argument type: ' .. type( julTime ) .. ': ' .. table.tostring( julTime )
end
end
julTimeISO8601 = mw.text.trim( julTimeISO8601 )
julTimeISO8601 = string.gsub( julTimeISO8601, '^+', '' )
local julTime = parseISO8601( julTimeISO8601 )
local t = os.date( "*t", julTime )
if ( julTime < parseISO8601( lowestBoundary ) ) then
-- only julian
if string.find( julTimeISO8601, '-02-29T', 1, true ) then
t = { year = t.year, month = 2, day = 29 }
end
return moduleDates.formatWikiImpl( t, t, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
end
if ( julTimeISO8601 >= lastBoundary ) then
return "''некорректная дата (юлианский календарь не используется после 1918-01-26)''"
end
-- julian and grigorian
for i = 1, #boundaries, 1 do
local b1 = boundaries[i][1]
local b2 = boundaries[i + 1][1]
if ( b1 <= julTimeISO8601 and julTimeISO8601 < b2 ) then
local diff = boundaries[i][2]
if string.sub( julTimeISO8601, 1, 10 ) == string.sub( boundaries[i][1], 1, 10 ) then
t = { year = t.year, month = 2, day = 29 }
diff = diff - 1
end
local gregTime = os.date( "*t", julTime + diff * 24 * 60 * 60 )
return moduleDates.formatWikiImpl( t, gregTime, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
end
end
return "''ошибка в модуле Модуль:Wikidata/date''"
end
return p
12c2c34efd103d2938bd65421aa550e8c6f26da0
Модуль:Sources
828
32
61
2024-06-10T20:41:59Z
wikipedia:ru>Stjn
0
возврат, сломало [[Википедия:Форум/Технический#Ошибка lua]]
Scribunto
text/plain
---@alias args table
---@alias frame { args: args, extensionTag: function, newChild: ( fun( args: args ): frame ) }
---@alias source { publication: source, [string]: any }
---@alias value: string | { id: string }
---@alias snak { datatype: string, snaktype: string, datavalue: { type: string, value: value } }
---@alias snaks table<string, table<number, snak>>
---@alias statement { mainsnak: snak, rank: string, qualifiers: snaks }
---@alias statements table<string, table<number, statement>>
---@alias map { name: string, ids: string[] }[]>
---@type table
local p = {}
---@type table<string, string>
local NORMATIVE_DOCUMENTS = {
Q20754888 = 'Закон Российской Федерации',
Q20754884 = 'Закон РСФСР',
Q20873831 = 'Распоряжение Президента Российской Федерации',
Q20873834 = 'Указ исполняющего обязанности Президента Российской Федерации',
Q2061228 = 'Указ Президента Российской Федерации',
}
---@type table<string, string>
local LANG_CACHE = {
Q150 = 'fr',
Q188 = 'de',
Q1321 = 'es',
Q1860 = 'en',
Q652 = 'it',
Q7737 = 'ru',
Q8798 = 'uk',
}
---@type map
local PROPERTY_MAP = {
{ name = 'sourceId', ids = { 'P248', 'P805' } },
{ name = 'lang', ids = { 'P407', 'P364' } },
{ name = 'author', ids = { 'P50', 'P2093' } },
{ name = 'part', ids = { 'P958', 'P1810' } },
{ name = 'title', ids = { 'P1476' } },
{ name = 'subtitle', ids = { 'P1680' } },
{ name = 'url', ids = { 'P953', 'P1065', 'P854', 'P973', 'P2699', 'P888' } },
{ name = 'editor', ids = { 'P98' } },
{ name = 'translator', ids = { 'P655' } },
{ name = 'publication-id', ids = { 'P1433' } },
{ name = 'edition', ids = { 'P393' } },
{ name = 'publisher', ids = { 'P123' } },
{ name = 'place', ids = { 'P291' } },
{ name = 'volume', ids = { 'P478' } },
{ name = 'issue', ids = { 'P433' } },
{ name = 'dateOfCreation', ids = { 'P571' } },
{ name = 'dateOfPublication', ids = { 'P577' } },
{ name = 'pages', ids = { 'P304' } },
{ name = 'numberOfPages', ids = { 'P1104' } },
{ name = 'tirage', ids = { 'P1092' } },
{ name = 'isbn', ids = { 'P212', 'P957' } },
{ name = 'issn', ids = { 'P236' } },
-- { name = 'accessdate', ids = { 'P813' } }, -- disable, creates duplicate references
{ name = 'docNumber', ids = { 'P1545' } },
{ name = 'type', ids = { 'P31' } },
{ name = 'arxiv', ids = { 'P818' } },
{ name = 'doi', ids = { 'P356' } },
{ name = 'pmid', ids = { 'P698' } },
}
-- table.insert( PROPERTY_MAP.url, 'P856' ) -- only as qualifier
---@type map
local PUBLICATION_PROPERTY_MAP = mw.clone( PROPERTY_MAP )
---@type string[]
local monthGen = { 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря' }
---@type string
local i18nDefaultLanguage = mw.language.getContentLanguage():getCode()
p.i18nDefaultLanguage = i18nDefaultLanguage
---@type string
local i18nEtAlDefault = ' et al.'
---@type table<string, string>
local i18nEtAl = {
ru = ' и др.',
uk = ' та ін.',
}
---@type table<string, string>
local i18nEditors = {
fr = '',
de = 'Hrsg.: ',
es = '',
en = '',
it = '',
ru = 'под ред. ',
uk = 'за ред. ',
}
---@type table<string, string>
local i18nTranslators = {
fr = '',
de = '',
es = '',
en = '',
it = '',
ru = 'пер. ',
uk = 'пер. ',
}
---@type table<string, string>
local i18nVolume = {
de = 'Vol.',
fr = 'Vol.',
es = 'Vol.',
en = 'Vol.',
it = 'Vol.',
ru = 'Т.',
uk = 'Т.',
}
---@type table<string, string>
local i18nIssue = {
en = 'Iss.',
ru = 'вып.',
uk = 'вип.',
}
---@type table<string, string>
local i18nPages = {
fr = 'P.',
de = 'S.',
es = 'P.',
en = 'P.',
it = 'P.',
ru = 'С.',
uk = 'С.',
}
---@type table<string, string>
local i18nNumberOfPages = {
en = 'p.',
ru = 'с.',
}
---@type table<string, string>
local i18nTirage = {
en = 'ed. size: %d',
ru = '%d экз.',
}
---@param args args
---@return source
local function getFilledArgs( args )
---@type source
local data = {}
for key, value in pairs( args ) do
if mw.text.trim( value ) ~= '' then
if key == 1 then
key = 'sourceId'
end
data[ key ] = mw.text.trim( value )
end
end
return data
end
---Returns formatted pair {Family name(s), First name(s)}
---@param fullName string
---@return table<number, string>
local function tokenizeName( fullName )
local space = '%s+' -- matches single or more spacing character
local name = "(%a[%a%-']*)%.?" -- matches single name, have to start with letter, can contain apostrophe and hyphen, may end with dot
local surname = "(%a[%a%-']*)" -- same as name, but can't end with dot
local surnamePrefixes = { 'ван', 'van', 'де', 'de' }
local nm, nm2, srn, srn2, pref
fullName = ' ' .. fullName .. ' '
fullName = mw.ustring.gsub( fullName, ' оглы ', ' ' )
fullName = mw.text.trim( fullName )
-- Surname, Name
local pattern = '^' .. surname .. ',' .. space .. name .. '$'
srn, nm = mw.ustring.match( fullName, pattern )
if srn then
return {
srn,
mw.ustring.sub( nm, 1, 1 ) .. '.'
}
end
-- Surname, Name prefix
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. surname .. ',' .. space .. name .. space .. '(' .. surnamePrefix .. ')' .. '$'
srn, nm, pref = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '.' }
end
end
-- Surname, Name Name
pattern = '^' .. surname .. ',' .. space .. name .. space .. name .. '$'
srn, nm, nm2 = mw.ustring.match( fullName, pattern )
if srn then
return {
srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
-- Surname Surname, Name
pattern = '^' .. surname .. space .. surname .. ',' .. space .. name .. '$'
srn, srn2, nm = mw.ustring.match( fullName, pattern )
if srn then
return {
srn .. ' ' .. srn2,
mw.ustring.sub( nm, 1, 1 ) .. '.'
}
end
-- Name Name Surname
pattern = '^' .. name .. space .. name .. space .. surname .. '$'
nm, nm2, srn = mw.ustring.match( fullName, pattern )
if srn then
return {
srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
-- Name Name prefix Surname
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. name .. space .. name .. space .. '(' .. surnamePrefix .. ')' .. space .. surname .. '$'
nm, nm2, pref, srn = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
end
-- Surname, Name Name prefix
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. surname .. ',' .. space .. name .. space .. name .. space .. '(' .. surnamePrefix .. ')' .. '$'
srn, nm, nm2, pref = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
end
-- Name{1,4} Surname
for k = 1, 4 do
pattern = '^' .. string.rep( name .. space, k ) .. surname .. '$'
---@type string[]
local matched = { mw.ustring.match( fullName, pattern ) }
if #matched ~= 0 then
for j = 1, k do
matched[ j ] = mw.ustring.sub( matched[ j ], 1, 1 )
end
return {
matched[ k + 1 ],
table.concat( matched, '. ', 1, k ) .. '.'
}
end
end
-- Surname Name{1,4}
for k = 1, 4 do
pattern = '^' .. surname .. string.rep( space .. name, k ) .. '$'
---@type string[]
local matched = { mw.ustring.match( fullName, pattern ) }
if #matched ~= 0 then
for j = 2, k + 1 do
matched[ j ] = mw.ustring.sub( matched[ j ], 1, 1 )
end
return {
matched[ 1 ],
table.concat( matched, '. ', 2, k + 1 ) .. '.'
}
end
end
return { fullName }
end
---@param fullName string | nil
---@return string | nil
local function personNameToAuthorName( fullName )
if not fullName then
return nil
end
local tokenized = tokenizeName( fullName )
if #tokenized == 1 then
return tokenized[ 1 ]
end
return tokenized[ 1 ] .. ' ' .. tokenized[ 2 ]
end
---@param fullName string | nil
---@return string | nil
local function personNameToResponsibleName( fullName )
if not fullName then
return nil
end
local tokenized = tokenizeName( fullName )
if #tokenized == 1 then
return tokenized[ 1 ]
end
return tokenized[ 2 ] .. ' ' .. tokenized[ 1 ]
end
---@alias options { separator: string, conjunction: string, format: ( fun( data: string ): string ), nolinks: boolean, preferids: boolean, short: boolean }
---@type options
local options_commas = {
separator = ', ',
conjunction = ', ',
format = function( data ) return data end,
nolinks = false,
preferids = false,
short = false,
}
---@type options
local options_commas_short = mw.clone( options_commas )
options_commas_short.short = true
---@type options
local options_commas_it_short = mw.clone( options_commas_short )
options_commas_it_short.format = function( data ) return "''" .. data .. "''" end
---@type options
local options_commas_nolinks = mw.clone( options_commas )
options_commas_nolinks.nolinks = true
---@type options
local options_citetypes = {
separator = ' ',
conjunction = ' ',
format = function( data ) return 'citetype_' .. data end,
nolinks = true ,
preferids = true,
short = false,
}
---@type options
local options_commas_authors = mw.clone( options_commas )
options_commas_authors.format = personNameToAuthorName
---@type options
local options_commas_responsible = mw.clone( options_commas )
options_commas_responsible.format = personNameToResponsibleName
---@type options
local options_ids = {
separator = '; ',
conjunction = '; ',
format = function( id ) return id end,
nolinks = true,
preferids = false,
short = false,
}
---@type options
local options_arxiv = mw.clone( options_ids )
options_arxiv.format = function( id ) return '[https://arxiv.org/abs/' .. id .. ' arXiv:' .. id .. ']' end
---@type options
local options_doi = mw.clone( options_ids )
options_doi.format = function( doi ) return '[https://dx.doi.org/' .. doi .. ' doi:' .. doi .. ']' end
---@type options
local options_issn = mw.clone( options_ids )
options_issn.format = function( issn ) return '[https://www.worldcat.org/issn/' .. issn .. ' ' .. issn .. ']' end
---@type options
local options_pmid = mw.clone( options_ids )
options_pmid.format = function( pmid ) return '[https://www.ncbi.nlm.nih.gov/pubmed/?term=' .. pmid .. ' PMID:' .. pmid .. ']' end
---@param str string | nil
---@return boolean
local function isEmpty( str )
return not str or #str == 0
end
---@param allQualifiers snaks
---@param qualifierPropertyId string
---@return string | nil
local function getSingleStringQualifierValue( allQualifiers, qualifierPropertyId )
if not allQualifiers or not allQualifiers[ qualifierPropertyId ] then
return nil
end
---@type table<number, snak>
local propertyQualifiers = allQualifiers[ qualifierPropertyId ]
for _, qualifier in pairs( propertyQualifiers ) do
if ( qualifier
and qualifier.datatype == 'string'
and qualifier.datavalue
and qualifier.datavalue.type == 'string'
and qualifier.datavalue.value ~= ''
) then
return qualifier.datavalue.value
end
end
return nil
end
---@param data table
---@param resultProperty string
---@return void
local function appendImpl_toTable( data, resultProperty )
if not data[ resultProperty ] then
data[ resultProperty ] = {}
elseif ( type( data[ resultProperty ] ) == 'string' or ( type( data[ resultProperty ] ) == 'table' and type( data[ resultProperty ].id ) == 'string' ) ) then
data[ resultProperty ] = { data[ resultProperty ] }
end
end
---@param datavalue table
---@param qualifiers snaks
---@param data table
---@param propertyName string
---@param options table
local function appendImpl( datavalue, qualifiers, data, propertyName, options )
data[ propertyName ] = data[ propertyName ] or {}
if propertyName == 'issn' then
table.insert( data[ propertyName ], datavalue.value )
elseif propertyName == 'url' or datavalue.type == 'url' then
local value = datavalue.value
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], value )
elseif datavalue.type == 'string' then
local value = getSingleStringQualifierValue( qualifiers, 'P1932' )
if not value then
value = getSingleStringQualifierValue( qualifiers, 'P1810' )
end
if not value then
value = datavalue.value
if options.format then
value = options.format( value )
end
end
appendImpl_toTable(data, propertyName)
local pos = getSingleStringQualifierValue( qualifiers, 'P1545' )
if pos then
table.insert( data[ propertyName ], tonumber(pos), value )
else
table.insert( data[ propertyName ], value )
end
elseif datavalue.type == 'monolingualtext' then
local value = datavalue.value.text
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], value )
elseif datavalue.type == 'quantity' then
local value = datavalue.value.amount
if ( mw.ustring.sub( value , 1, 1 ) == '+' ) then
value = mw.ustring.sub( value , 2 )
end
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], value )
elseif datavalue.type == 'wikibase-entityid' then
local pos = getSingleStringQualifierValue( qualifiers, 'P1545' )
local value = datavalue.value
appendImpl_toTable(data, propertyName)
local label = getSingleStringQualifierValue( qualifiers, 'P1932' )
if not label then
label = getSingleStringQualifierValue( qualifiers, 'P1810' )
end
local toInsert = {
id = value.id,
label = label
}
if pos and tonumber( pos ) then
table.insert( data[ propertyName ], tonumber( pos ), toInsert )
else
table.insert( data[ propertyName ], toInsert )
end
elseif datavalue.type == 'time' then
local value = datavalue.value
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], tostring( value.time ) )
end
end
---@param entityId string
---@param propertyId string
---@return table<number, statement>
local function getAllStatements( entityId, propertyId )
---@type boolean, table<number, statement>
local wdStatus, statements = pcall( mw.wikibase.getAllStatements, entityId, propertyId )
if wdStatus and statements then
return statements
end
return {}
end
---@param entityId string
---@param propertyId string
---@return table<number, statement>
local function getBestStatements( entityId, propertyId )
---@type boolean, table<number, statement>
local wdStatus, statements = pcall( mw.wikibase.getBestStatements, entityId, propertyId )
if wdStatus and statements then
return statements
end
return {}
end
---@param entityId string
---@param projectToCheck string?
---@return string | nil
local function getSitelink( entityId, projectToCheck )
---@type boolean, string
local wbStatus, sitelink
if projectToCheck then
wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId, projectToCheck )
else
wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId )
end
if not wbStatus then
return nil
end
return sitelink
end
---@param args any[]
---@return any | nil
local function coalesce( args )
for _, arg in pairs( args ) do
if not isEmpty( arg ) then return arg end
end
return nil
end
---@param value any
---@return string | nil
local function getSingle( value )
if type( value ) == 'string' then
return tostring( value )
elseif type( value ) == 'table' then
if value.id then
return tostring( value.id )
end
for _, tableValue in pairs( value ) do
return getSingle( tableValue )
end
end
return nil
end
---@param langEntityId string
---@return string | nil
local function getLangCode( langEntityId )
if not langEntityId then
return nil
end
langEntityId = getSingle( langEntityId )
if not string.match( langEntityId, '^Q%d+$' ) then
return langEntityId
end
local cached = LANG_CACHE[ langEntityId ]
if cached then
if cached == '' then
return nil
end
return cached
end
local claims = getBestStatements( langEntityId, 'P424' )
for _, claim in pairs( claims ) do
if claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
then
LANG_CACHE[ langEntityId ] = claim.mainsnak.datavalue.value
return claim.mainsnak.datavalue.value
end
end
LANG_CACHE[ langEntityId ] = ''
return nil
end
---@param entityId string
---@param propertyId string
---@param data source
---@param propertyName string
---@param options table?
---@return void
local function appendEntitySnaks( entityId, propertyId, data, propertyName, options )
options = options or {}
-- do not populate twice
if data[ propertyName ] and ( propertyName ~= 'author' or data[ propertyId ] ) then
return
end
local statements = getBestStatements( entityId, propertyId )
if propertyName == 'author' then
data[ propertyId ] = true
end
local lang = getLangCode( data.lang ) or i18nDefaultLanguage
if propertyId == 'P1680' then -- if there is a default language
for _, statement in pairs( statements ) do
if statement and
statement.mainsnak and
statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.language == lang
then
--found default language string
appendImpl( statement.mainsnak.datavalue, statement.qualifiers, data, propertyName, options )
return
end
end
end
for _, statement in pairs( statements ) do
if statement and statement.mainsnak and statement.mainsnak.datavalue then
appendImpl( statement.mainsnak.datavalue, statement.qualifiers or {}, data, propertyName, options )
if propertyName == 'publication-id' and statement.qualifiers then
data[ 'publication-qualifiers' ] = statement.qualifiers
end
end
end
end
---@param claims table<number, statement>
---@param qualifierPropertyId string
---@param result table
---@param resultPropertyId string
---@param options table
---@return void
local function appendQualifiers( claims, qualifierPropertyId, result, resultPropertyId, options )
-- do not populate twice
if not claims or result[ resultPropertyId ] then
return
end
for _, claim in pairs( claims ) do
if claim.qualifiers and claim.qualifiers[ qualifierPropertyId ] then
---@type table<number, snak>
local propertyQualifiers = claim.qualifiers[ qualifierPropertyId ]
for _, qualifier in pairs( propertyQualifiers ) do
if qualifier and qualifier.datavalue then
appendImpl( qualifier.datavalue, nil, result, resultPropertyId, options )
end
end
end
end
end
---@param entityId string
---@param propertyId string
---@param value any
---@return table<number, statement>
local function findClaimsByValue( entityId, propertyId, value )
local result = {}
local claims = getAllStatements( entityId, propertyId )
for _, claim in pairs( claims ) do
if ( claim.mainsnak and claim.mainsnak.datavalue ) then
local datavalue = claim.mainsnak.datavalue
if ( datavalue.type == "string" and datavalue.value == value ) or
( datavalue.type == "wikibase-entityid" and
datavalue.value[ "entity-type" ] == "item" and
tostring( datavalue.value.id ) == value )
then
table.insert( result, claim )
end
end
end
return result
end
---@param entityId string
---@param typeEntityId string
---@return boolean
local function isInstanceOf( entityId, typeEntityId )
return findClaimsByValue( entityId, 'P31', typeEntityId )[ 1 ] ~= nil
end
---@param entityId string
---@param typeEntityIds string[]
---@return string
---@todo Rewrite
local function getFirstType( entityId, typeEntityIds )
for _, typeEntityId in pairs( typeEntityIds ) do
if isInstanceOf( entityId, typeEntityId ) then
return typeEntityId
end
end
return nil
end
---@param snaks snaks
---@param data source
---@param map map
---@return void
local function populateDataFromSnaks( snaks, data, map )
for _, row in ipairs( map ) do
local parameterName, propertyIds = row.name, row.ids
for _, propertyId in pairs( propertyIds ) do
if not data[ parameterName ] and snaks[ propertyId ] then
local options = {}
if propertyId == 'P888' then
options = { format = function( id ) return 'http://www.jstor.org/stable/' .. id end }
end
for _, snak in pairs( snaks[ propertyId ] ) do
if snak and snak.datavalue then
appendImpl( snak.datavalue, {}, data, parameterName, options )
end
end
end
end
end
end
---@param entityId string | nil
---@param data source
---@param map map
---@return void
local function populateDataFromEntity( entityId, data, map )
if not data.title then
if not isEmpty( entityId ) then
local optionsAsLinks = { format = function( text ) return { id = entityId, label = text } end }
appendEntitySnaks( entityId, 'P1476', data, 'title', optionsAsLinks )
else
appendEntitySnaks( entityId, 'P1476', data, 'title', {} )
end
appendEntitySnaks( entityId, 'P1680', data, 'subtitle', {} )
end
local bookSeriesStatements = getBestStatements( entityId, 'P361' )
for _, statement in pairs( bookSeriesStatements ) do
if statement and
statement.mainsnak and
statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.id
then
local possibleBookSeriesEntityId = statement.mainsnak.datavalue.value.id
if isInstanceOf( possibleBookSeriesEntityId, 'Q277759' ) then
appendImpl_toTable( data, 'bookSeries' )
table.insert( data.bookSeries, { id = possibleBookSeriesEntityId } )
appendQualifiers( { statement }, 'P478', data, 'bookSeriesVolume', {} )
appendQualifiers( { statement }, 'P433', data, 'bookSeriesIssue', {} )
end
end
end
for _, row in ipairs( map ) do
local parameterName, propertyIds = row.name, row.ids
for _, propertyId in pairs( propertyIds ) do
local options = {}
if propertyId == 'P888' then
options = { format = function( id ) return 'http://www.jstor.org/stable/' .. id end }
end
appendEntitySnaks( entityId, propertyId, data, parameterName, options )
end
end
end
---@param data source
---@return void
local function expandPublication( data )
if not data[ 'publication-id' ] then
return
end
local publicationId = getSingle( data[ 'publication-id' ] )
data.publication = {}
for key, value in pairs( data ) do
if not string.match( key, '^publication-' ) then
data.publication[ key ] = value
end
end
data.publication.sourceId = publicationId
data.publication.title = data[ 'publication-title' ]
data.publication.subtitle = data[ 'publication-subtitle' ]
if data[ 'publication-qualifiers' ] then
populateDataFromSnaks( data[ 'publication-qualifiers' ], data.publication, PUBLICATION_PROPERTY_MAP )
end
populateDataFromEntity( publicationId, data.publication, PUBLICATION_PROPERTY_MAP )
if type( data.publication.title ) == 'table' and data.publication.title[ 1 ] then
data.publication.title = data.publication.title[ 1 ]
end
if type( data.publication.subtitle ) == 'table' and data.publication.subtitle[ 1 ] then
data.publication.subtitle = data.publication.subtitle[ 1 ]
end
for key, value in pairs( data.publication ) do
if key ~= 'sourceId' and key ~= 'title' and key ~= 'subtitle' and key ~= 'url' and not data[ key ] then
data[ key ] = value
end
end
end
---@param data source
---@return void
local function expandBookSeries( data )
local bookSeries = data.bookSeries
if not bookSeries then
return
end
-- use only first one
if type( bookSeries ) == 'table' and bookSeries[ 1 ] and bookSeries[ 1 ].id then
data.bookSeries = bookSeries[ 1 ]
bookSeries = data.bookSeries
end
if not bookSeries or not bookSeries.id then
return
end
appendEntitySnaks( bookSeries.id, 'P123', data, 'publisher', {} )
appendEntitySnaks( bookSeries.id, 'P291', data, 'place', {} )
appendEntitySnaks( bookSeries.id, 'P236', data, 'issn', {} )
end
---@param entityId string
---@return string | nil
local function getNormativeTitle( entityId )
local possibleTypeIds = {}
for typeId, _ in pairs( NORMATIVE_DOCUMENTS ) do
table.insert( possibleTypeIds, typeId )
end
local foundTypeId = getFirstType( entityId, possibleTypeIds )
if foundTypeId then
return NORMATIVE_DOCUMENTS[ foundTypeId ]
end
return nil
end
---@param urls table<number, string> | string
---@param text string
---@return string
local function wrapInUrl( urls, text )
local url = getSingle( urls )
if string.sub( url, 1, 1 ) == ':' then
return '[[' .. url .. '|' .. text .. ']]'
else
return '[' .. url .. ' ' .. text .. ']'
end
end
---@param entityId string
---@param lang string
---@return string
local function getElementLink( entityId, lang )
local sitelink = getSitelink( entityId, nil )
if sitelink then
return ':' .. sitelink
end
if lang ~= 'mul' then
-- link to entity in source language
sitelink = getSitelink( entityId, lang .. 'wiki' )
if sitelink then
return ':' .. lang .. ':' .. sitelink
end
end
return ':d:' .. entityId
end
---@param entityId string
---@param lang string
---@return string
local function getLabel( entityId, lang )
local wbStatus, label = pcall( mw.wikibase.getLabelByLang, entityId, lang )
if not wbStatus then
return ''
end
if label and label ~= '' then
return label
end
wbStatus, label = pcall( mw.wikibase.getLabel, entityId )
if not wbStatus then
return ''
end
return label or ''
end
---@param lang string
---@param entityId string
---@param customTitle string
---@param options table
local function renderLink( lang, entityId, customTitle, options )
if not entityId then
error( 'entityId is not specified' )
end
if type( entityId ) ~= 'string' then
error( 'entityId is not string, but ' .. type( entityId ) )
end
if type( customTitle or '' ) ~= 'string' then
error( 'customTitle is not string, but ' .. type( customTitle ) )
end
local title = customTitle
-- ISO 4
if isEmpty( title ) then
local propertyStatements = getBestStatements( entityId, 'P1160' )
for _, claim in pairs( propertyStatements ) do
if ( claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
and claim.mainsnak.datavalue.value.language == lang
) then
title = claim.mainsnak.datavalue.value.text
-- mw.log( 'Got title of ' .. entityId .. ' from ISO 4 claim: «' .. title .. '»' )
break
end
end
end
-- official name P1448
-- short name P1813
if isEmpty( title ) and options.short then
local propertyStatements = getBestStatements( entityId, 'P1813' )
for _, claim in pairs( propertyStatements ) do
if ( claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
and claim.mainsnak.datavalue.value.language == lang
) then
title = claim.mainsnak.datavalue.value.text
-- mw.log( 'Got title of ' .. entityId .. ' from short name claim: «' .. title .. '» (' .. lang .. ')' )
break
end
end
end
-- person name P1559
-- labels
if isEmpty( title ) then
title = getLabel( entityId, lang )
-- mw.log( 'Got title of ' .. entityId .. ' from label: «' .. title .. '» (' .. lang .. ')' )
end
local actualText = title or '\'\'(untranslated)\'\''
local link = getElementLink( entityId, lang )
return wrapInUrl( link, actualText )
end
---@param lang string
---@param value value
---@param options options
---@return string
local function asString( lang, value, options )
if type( value ) == 'string' then
return options.format( value )
end
if type( value ) ~= 'table' then
return options.format( '(unknown type)' )
end
if value.id then
-- this is link
if type( value.label or '' ) ~= 'string' then
mw.logObject( value, 'error value' )
error( 'label of table value is not string but ' .. type( value.label ) )
end
local title
if options.preferids then
title = value.id
elseif options.nolinks then
title = value.label or getLabel( value.id, lang )
else
title = renderLink( lang, value.id, value.label, options )
end
if title == '' then
title = "''(untranslated title)''"
end
return options.format( title )
end
local resultList = {}
for _, tableValue in pairs( value ) do
table.insert( resultList, asString( lang, tableValue, options ) )
end
return mw.text.listToText( resultList, options.separator, options.conjunction )
end
---@param entityId string
---@param data source
---@return source
local function populateSourceDataImpl( entityId, data, map )
local wsLink = getSitelink( entityId, 'ruwikisource' )
if wsLink and not mw.ustring.gmatch( wsLink, 'Категория:' ) then
data.url = ":ru:s:" .. wsLink
end
populateDataFromEntity( entityId, data, map )
local normativeTitle = getNormativeTitle( entityId )
if normativeTitle then
local y, m, d = mw.ustring.match( getSingle( data.dateOfCreation ) , "(%-?%d+)%-(%d+)%-(%d+)T" )
y, m, d = tonumber( y ),tonumber( m ), tonumber( d )
local title = asString( 'ru', data.title, options_commas_nolinks )
local docNumber = getSingle( data.docNumber )
data.title = {
normativeTitle ..
" от " .. tostring( d ) .. " " .. monthGen[ m ] .. " " .. tostring( y ) .. " г." ..
( docNumber and ( " № " .. docNumber ) or '' ) ..
' «' .. title.. '»'
}
end
if not data.title then
local lang = getLangCode( data.lang ) or i18nDefaultLanguage
local label = getLabel( entityId, lang )
if label ~= '' then
data.title = { label }
end
end
return data
end
---@param entityId string
---@param propertyId string
---@param data source
---@return void
local function expandSpecialsQualifiers( entityId, propertyId, data )
local statements = getBestStatements( entityId, propertyId )
for _, statement in pairs( statements ) do
populateDataFromSnaks( statement.qualifiers or {}, data, PROPERTY_MAP )
end
end
---Expand special types of references when additional data could be found in OTHER entity properties
---@param data source
---@return void
local function expandSpecials( data )
if not data.entityId then
return
end
if data.sourceId == 'Q36578' then
-- Gemeinsame Normdatei -- specified by P227
appendEntitySnaks( data.entityId, 'P227', data, 'part', { format = function(gnd ) return 'Record #' .. gnd; end } )
appendEntitySnaks( data.entityId, 'P227', data, 'url', { format = function(gnd ) return 'http://d-nb.info/gnd/' .. gnd .. '/'; end } )
data.year = '2012—2016'
expandSpecialsQualifiers( data.entityId, 'P227', data )
elseif data.sourceId == 'Q15222191' then
-- BNF -- specified by P268
appendEntitySnaks( data.entityId, 'P268', data, 'part', { format = function(id ) return 'Record #' .. id; end } )
appendEntitySnaks( data.entityId, 'P268', data, 'url', { format = function(id ) return 'http://catalogue.bnf.fr/ark:/12148/cb' .. id; end } )
expandSpecialsQualifiers( data.entityId, 'P268', data )
elseif data.sourceId == 'Q54919' then
-- VIAF -- specified by P214
appendEntitySnaks( data.entityId, 'P214', data, 'part', { format = function(id ) return 'Record #' .. id; end } )
appendEntitySnaks( data.entityId, 'P214', data, 'url', { format = function(id ) return 'https://viaf.org/viaf/' .. id; end } )
expandSpecialsQualifiers( data.entityId, 'P214', data )
else
-- generic property search
for _, sourceClaim in pairs( getBestStatements( data.sourceId, 'P1687' ) ) do
if sourceClaim.mainsnak.snaktype == 'value' then
local sourcePropertyId = sourceClaim.mainsnak.datavalue.value.id
for _, sourcePropertyClaim in pairs( getBestStatements( sourcePropertyId, 'P1630' ) ) do
if sourcePropertyClaim.mainsnak.snaktype == 'value' then
appendEntitySnaks( data.entityId, sourcePropertyId, data, 'url', {
format = function( id )
return mw.ustring.gsub( mw.ustring.gsub( sourcePropertyClaim.mainsnak.datavalue.value, '$1', id ), ' ', '%%20' )
end
} )
expandSpecialsQualifiers( data.entityId, sourcePropertyId, data )
break
end
end
end
end
end
-- do we have appropriate record in P1433 ?
local claims = findClaimsByValue( currentEntityId, 'P1343', data.sourceId )
if claims and #claims ~= 0 then
for _, claim in pairs( claims ) do
populateDataFromSnaks( claim.qualifiers, data, PROPERTY_MAP )
populateDataFromEntity( data.sourceId, data, PROPERTY_MAP )
end
end
end
---@param text string
---@param tip string
---@return string
local function toTextWithTip( text, tip )
return '<span title="' .. tip .. '" style="border-bottom: 1px dotted; cursor: help; white-space: nowrap">' .. text .. '</span>'
end
---@param lang string
---@param placeId string
---@return string
local function getPlaceName( placeId, lang )
-- ГОСТ Р 7.0.12—2011
if lang == 'ru' then
if placeId == 'Q649' then return toTextWithTip( 'М.', 'Москва' ); end
if placeId == 'Q656' then return toTextWithTip( 'СПб.', 'Санкт-Петербург' ); end
if placeId == 'Q891' then return toTextWithTip( 'Н. Новгород', 'Нижний Новгород' ); end
if placeId == 'Q908' then return toTextWithTip( 'Ростов н/Д.', 'Ростов-на-Дону' ); end
end
return nil
end
---@param data source
---@param lang string
---@return void
local function preprocessPlace( data, lang )
if not data.place then
return
end
---@type table<number, string>
local newPlace = {}
for index, place in pairs( data.place ) do
if place.id then
local newPlaceStr = getPlaceName( place.id, lang )
if newPlaceStr then
newPlace[ index ] = newPlaceStr
else
newPlace[ index ] = getLabel( place.id, lang )
end
else
newPlace[ index ] = place
end
end
data.place = newPlace
end
---@param entityId string
---@param lang string
---@param providedLabel string | nil
---@param options options
---@return string
local function getPersonNameAsLabel( entityId, lang, providedLabel, options )
-- would custom label provided we don't need to check entity at all
if not isEmpty( providedLabel ) then
return options.format( providedLabel )
end
if lang == 'mul' then
lang = i18nDefaultLanguage
end
---@type string | nil
local personName = getLabel( entityId, lang )
if isEmpty( personName ) then
return '\'\'(not translated to ' .. lang .. ')\'\''
end
if not isInstanceOf( entityId, 'Q5' ) then
return personName
end
return options.format( personName )
end
---@param entityId string
---@param lang string
---@param customLabel string | nil
---@param options options
---@return string
local function getPersonNameAsWikitext( entityId, lang, customLabel, options )
local personName = getPersonNameAsLabel( entityId, lang, customLabel, options )
local link = getElementLink( entityId, lang )
return wrapInUrl( link, personName )
end
---@param value value
---@param lang string
---@param options options
---@return string
local function getPeopleAsWikitext( value, lang, options )
if type( value ) == 'string' then
return options.format( value )
elseif type( value ) == 'table' then
if value.id then
-- this is link
if options.preferids then
return tostring( value.id )
else
if options.nolinks then
return getPersonNameAsLabel( value.id, lang, value.label, options )
else
return getPersonNameAsWikitext( value.id, lang, value.label, options )
end
end
end
local maxAuthors = 10 -- need some restrictions, as some publications have enormous amount of authors (e.g. 115 authors of Q68951544)
local resultList = {}
for _, tableValue in pairs( value ) do
local nextWikitext = getPeopleAsWikitext( tableValue, lang, options )
if not isEmpty( nextWikitext ) then
table.insert( resultList, nextWikitext )
if #resultList == maxAuthors + 1 then
-- keep one more to indicate that there are too many
break
end
end
end
local resultWikitext = ''
for i, wikitext in pairs( resultList ) do
if i == maxAuthors + 1 then
resultWikitext = resultWikitext .. ( i18nEtAl[ lang ] or i18nEtAlDefault )
break
end
if i ~= 1 then
resultWikitext = resultWikitext .. ', '
end
resultWikitext = resultWikitext .. wikitext
end
return resultWikitext
end
return '' -- options.format( '(unknown type)' )
end
---@param lang string
---@param data source
---@return string
local function generateAuthorLinks( lang, data )
local result = ''
if data.author then
result = getPeopleAsWikitext( data.author, lang, options_commas_authors )
result = '<i class="wef_low_priority_links">' .. result .. '</i> '
end
return result
end
---@param lang string
---@param data source
---@param conjunction string
---@param propertyName string
---@param urlPropertyName string?
---@return string
local function appendProperty( lang, data, conjunction, propertyName, urlPropertyName )
if not data[ propertyName ] then
return ''
end
local out
if urlPropertyName and data[ urlPropertyName ] then
out = wrapInUrl( data[ urlPropertyName ], asString( lang, data[ propertyName ], options_commas_nolinks ) )
else
out = asString( lang, data[ propertyName ], options_commas )
end
if not out or out == '' then
return ''
end
return conjunction .. out
end
---@param lang string
---@param data source
---@return string
local function appendTitle( lang, data )
local conjunction = ''
local result = ''
if data.part then
result = result .. appendProperty( lang, data, '', 'part', 'parturl' )
conjunction = ' // '
end
return result .. appendProperty( lang, data, conjunction, 'title', 'url' )
end
---@param lang string
---@return string
local function appendLanguage( lang )
if lang == i18nDefaultLanguage then
return ''
end
---@type { getRefHtml: ( fun( lang: string ): string ), list_ref: ( fun( frame: frame ): string ) }
local langs = require( 'Module:Languages' )
return langs.list_ref( p.currentFrame:newChild{ args = { lang } } )
end
---@param lang string
---@param data source
---@return string
local function appendSubtitle( lang, data )
return appendProperty( lang, data, ': ', 'subtitle', nil )
end
---@param lang string
---@param data source
---@return string
local function appendOriginalTitle( lang, data )
return appendProperty( lang, data, ' = ', 'originaltitle', nil )
end
---@param lang string
---@param data source
---@return string
local function appendPublication( lang, data )
if not data.publication then
return ''
end
local result = ' // ' .. asString( lang, data.publication.title, options_commas_it_short )
if data.publication.subtitle and data.publication.subtitle ~= '' then
result = result .. ': ' .. asString( lang, data.publication.subtitle, options_commas_it_short )
end
return result
end
---@param lang string
---@param data source
---@return string
local function appendEditor( lang, data )
if not data.editor and not data.translator then
return ''
end
local result = ' / '
if data.editor then
local prefix = i18nEditors[ lang ] or i18nEditors[ i18nDefaultLanguage ]
result = result .. prefix .. getPeopleAsWikitext( data.editor, lang, options_commas_responsible )
if data.translator then
result = result .. ', '
end
end
if data.translator then
local prefix = i18nTranslators[ lang ] or i18nTranslators[ i18nDefaultLanguage ]
result = result .. prefix .. getPeopleAsWikitext( data.translator, lang, options_commas_responsible )
end
return result
end
---@param lang string
---@param data source
local function appendEdition( lang, data )
return appendProperty( lang, data, ' — ', 'edition', nil )
end
---@param lang string
---@param data source
---@return string
local function appendPublicationData( lang, data )
if not data.place and not data.publisher and not data.year then
return ''
end
local result = ' — '
if data.place then
result = result .. asString( lang, data.place, options_commas_short )
if data.publisher or data.year then
result = result .. ': '
end
end
if data.publisher then
result = result .. asString( lang, data.publisher, options_commas_short )
if data.year then
result = result .. ', '
end
end
if data.year then
result = result .. asString( lang, data.year, options_commas )
end
result = result .. '.'
return result
end
---@param lang string
---@param data source
---@return string
local function appendVolumeAndIssue( lang, data )
if not data.volume and not data.issue then
return ''
end
local result = ' — '
local letter_vol = i18nVolume[ lang ] or i18nVolume[ i18nDefaultLanguage ]
local letter_iss = i18nIssue[ lang ] or i18nIssue[ i18nDefaultLanguage ]
if data.volume then
result = result .. appendProperty( lang, data, letter_vol .. ' ', 'volume', nil )
result = result ..appendProperty( lang, data, ', ' .. letter_iss .. ' ', 'issue', nil )
else
result = result .. appendProperty( lang, data, letter_iss .. ' ', 'issue', nil )
end
result = result .. '.'
return result
end
---@param lang string
---@param data source
---@return string
local function appendPages( lang, data )
if not data.pages then
return ''
end
local letter = i18nPages[ lang ] or i18nPages[ i18nDefaultLanguage ]
local strPages = asString( lang, data.pages, options_commas )
strPages = mw.ustring.gsub( strPages, '[-—]', '—' )
return ' — ' .. letter .. ' ' .. strPages .. '.'
end
---@param lang string
---@param data source
---@return string
local function appendNumberOfPages( lang, data )
if not data.numberOfPages then
return ''
end
local letter = i18nNumberOfPages[ lang ] or i18nNumberOfPages[ i18nDefaultLanguage ]
return appendProperty( lang, data, ' — ', 'numberOfPages', nil ) .. ' ' .. letter
end
---@param lang string
---@param data source
---@return string
local function appendBookSeries( lang, data )
if not data.bookSeries then
return ''
end
local result = appendProperty( lang, data, ' — (', 'bookSeries', nil )
if data.bookSeriesVolume or data.bookSeriesIssue then
result = result .. '; '
local letter_vol = i18nVolume[ lang ] or i18nVolume[ i18nDefaultLanguage ]
local letter_iss = i18nIssue[ lang ] or i18nIssue[ i18nDefaultLanguage ]
if data.bookSeriesVolume then
result = result .. appendProperty( lang, data, letter_vol .. ' ', 'bookSeriesVolume', nil )
result = result .. appendProperty( lang, data, ', ' .. letter_iss .. ' ', 'bookSeriesIssue', nil )
else
result = result .. appendProperty( lang, data, letter_iss .. ' ', 'bookSeriesIssue', nil )
end
end
result = result .. ')'
return result
end
---@param lang string
---@param data source
---@return string
local function appendTirage( lang, data )
if not data.tirage then
return ''
end
local tirageTemplate = i18nTirage[ lang ] or i18nTirage[ i18nDefaultLanguage ]
---@type options
local optionsTirage = {
separator = '; ',
conjunction = '; ',
format = function( _data ) return tostring( mw.ustring.format( tirageTemplate, _data ) ) end,
short = false,
nolinks = false,
preferids = false,
}
return ' — ' .. asString( lang, data.tirage, optionsTirage )
end
---@param lang string
---@param value string | nil
---@param options options
---@param prefix string?
---@return string
local function appendIdentifier( lang, value, options, prefix )
if not value then
return ''
end
return ' — ' .. ( prefix or '' ) .. asString( lang, value, options )
end
---@param result string
---@param lang string
---@param data source
---@return string
local function wrapSourceId( result, lang, data )
if not data.sourceId then
return result
end
local citeType = data.type and asString( lang, data.type, options_citetypes ) or 'citetype_unknown'
return '<span class="wikidata_cite ' .. citeType .. '" data-entity-id="' .. data.sourceId .. '">' .. result .. '</span>'
end
---@param data source
---@return string
local function appendAccessDate( data )
if not data.accessdate then
return ''
end
local date = getSingle( data.accessdate )
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local y, m, d = mw.ustring.match( date, pattern )
y, m, d = tonumber( y ), tonumber( m ), tonumber( d )
local date_str = ( d > 0 and ' ' .. tostring( d ) or '' )
.. ( m > 0 and ' ' .. monthGen[ m ] or '' )
.. ( y > 0 and ' ' .. tostring( y ) or '' )
return " <small>Проверено" .. date_str .. ".</small>"
end
---@param data source
---@param lang string
---@return void
local function populateUrl( data, lang )
if data.sourceId and not data.url then
local sitelink = getSitelink( data.sourceId, lang .. 'wikisource' )
if sitelink then
data.url = ':' .. lang .. ':s:' .. sitelink
end
end
end
---@param data source
---@return void
local function populateYear( data )
if not data.year and data.dateOfPublication then
local date = getSingle( data.dateOfPublication )
data.year = mw.ustring.sub( date, 2, 5 )
end
if not data.year and data.dateOfCreation then
local date = getSingle( data.dateOfCreation )
data.year = mw.ustring.sub( date, 2, 5 )
end
end
---@param data source
---@return void
local function populateTitle( data )
data.title = data.title or getSingle( data.url )
end
---@param data source
---@return string
local function renderSource( data )
local lang = getLangCode( data.lang ) or i18nDefaultLanguage
preprocessPlace( data, lang )
populateUrl( data, lang )
populateTitle( data )
if not data.title then
return ''
end
populateYear( data )
local result = generateAuthorLinks( lang, data )
result = result .. appendTitle( lang, data )
result = result .. appendLanguage( lang )
result = result .. appendSubtitle( lang, data )
result = result .. appendOriginalTitle( lang, data )
result = result .. appendPublication( lang, data )
result = result .. '<span class="wef_low_priority_links">'
result = result .. appendEditor( lang, data ) -- Might take current editor instead of actual. Use with caution
result = result .. appendEdition( lang, data )
result = result .. appendPublicationData( lang, data )
result = result .. appendVolumeAndIssue( lang, data )
result = result .. appendPages( lang, data )
result = result .. appendNumberOfPages( lang, data )
result = result .. appendBookSeries( lang, data )
result = result .. appendTirage( lang, data )
result = result .. appendIdentifier( lang, data.isbn, options_commas, 'ISBN ' )
result = result .. appendIdentifier( lang, data.issn, options_issn, 'ISSN ' )
result = result .. appendIdentifier( lang, data.doi, options_doi, nil )
result = result .. appendIdentifier( lang, data.pmid, options_pmid, nil )
result = result .. appendIdentifier( lang, data.arxiv, options_arxiv, nil )
result = result .. appendAccessDate( data )
result = result .. '</span>'
return wrapSourceId( result, lang, data )
end
---@param data source Данные в простом формате, согласованном с модулями формирования библиографического описания
---@param snaks snaks
---@return string | nil
local function renderReferenceImpl( data, snaks )
-- не показывать источники с "импортировано из"
if snaks.P143 then
return nil
end
-- забрать данные из reference
populateDataFromSnaks( snaks or {}, data, PROPERTY_MAP )
data.sourceId = getSingle( data.sourceId )
populateDataFromEntity( data.sourceId, data, PROPERTY_MAP )
expandSpecials( data )
populateSourceDataImpl( data.sourceId, data, PROPERTY_MAP )
expandPublication( data )
expandBookSeries( data )
if next( data ) == nil then
return nil
end
local rendered = renderSource( data )
if mw.ustring.len( rendered ) == 0 then
return nil
end
if data.ref then
local anchorValue = 'CITEREF' .. data.ref .. ( coalesce( { data[ 'ref-year' ], data.year } ) or '' )
rendered = '<span class="citation" id="' .. mw.uri.anchorEncode( anchorValue ) .. '">' .. rendered .. '</span>'
end
return rendered
end
---@param frame frame
---@param currentEntityId string | { id: string }
---@param reference table{ snaks: snaks }
---@return string | nil
function p.renderSource( frame, currentEntityId, reference )
reference = reference or { snaks = {} }
p.currentFrame = frame
local data = getFilledArgs( frame.args or {} )
populateDataFromSnaks( reference.snaks, data, PROPERTY_MAP )
data.sourceId = getSingle( data.sourceId )
if not currentEntityId then
data.entityId = mw.wikibase.getEntityIdForCurrentPage()
elseif type( currentEntityId ) == 'string' then
data.entityId = currentEntityId
elseif type( currentEntityId ) == 'table' and currentEntityId.id then
data.entityId = currentEntityId.id
end
---@type string
local rendered = renderReferenceImpl( data, reference.snaks or {} )
if not rendered then
return ''
end
return rendered
end
---@param frame frame
---@param currentEntityId string
---@param reference table
---@return string
function p.renderReference( frame, currentEntityId, reference )
local rendered = p.renderSource( frame, currentEntityId, reference )
if not rendered or rendered == '' then
return ''
end
-- Про выбор алгоритма хеширования см. [[Модуль:Hash]]. Знак подчёркивания в начале позволяет
-- исключить ошибку, когда имя сноски — чисто числовое значение, каковыми иногда бывают хеши.
return frame:extensionTag( 'ref', rendered, { name = '_' .. mw.hash.hashValue( 'fnv164', rendered ) } ) .. '[[Category:Википедия:Статьи с источниками из Викиданных]]'
end
---@param frame frame
---@return string | nil
function p.testPersonNameToAuthorName( frame )
return personNameToAuthorName( frame.args[ 1 ] )
end
---@param frame frame
---@return string | nil
function p.testPersonNameToResponsibleName( frame )
return personNameToResponsibleName( frame.args[ 1 ] )
end
return p
752a204827a41ecd6cf518bdb22da12718bca2ec
Модуль:Message box/ombox.css
828
111
219
2024-06-21T16:47:35Z
wikipedia:ru>Putnik
0
исправление цвета рамки
text
text/plain
/* Скопировано из [[:en:Module:Message box/ombox.css]] */
.ombox {
margin: 4px 0;
border-collapse: collapse;
border: 1px solid var(--border-color-base, #a2a9b1); /* Default "notice" gray */
background-color: var(--background-color-neutral-subtle, #f8f9fa);
box-sizing: border-box;
}
/* For the "small=yes" option. */
.ombox.mbox-small {
font-size: 88%;
line-height: 1.25em;
}
.ombox-speedy {
border: 2px solid var(--border-color-error, #b32424); /* Red */
background-color: var(--background-color-error-subtle, #fee7e6); /* Pink */
}
.ombox-delete {
border: 2px solid var(--background-color-error--active, #b32424); /* Red */
}
.ombox-content {
border: 1px solid #f28500; /* Orange */
}
.ombox-style {
border: 1px solid #fc3; /* Yellow */
}
.ombox-move {
border: 1px solid #9932cc; /* Purple */
}
.ombox-protection {
border: 2px solid var(--border-color-base, #a2a9b1); /* Gray-gold */
}
.ombox .mbox-text {
border: none;
/* @noflip */
padding: 0.25em 0.9em;
width: 100%;
}
.ombox .mbox-image {
border: none;
/* @noflip */
padding: 2px 0 2px 0.9em;
text-align: center;
}
.ombox .mbox-imageright {
border: none;
/* @noflip */
padding: 2px 0.9em 2px 0;
text-align: center;
}
/* An empty narrow cell */
.ombox .mbox-empty-cell {
border: none;
padding: 0;
width: 1px;
}
.ombox .mbox-invalid-type {
text-align: center;
}
/* Хак, TODO: посмотреть, как оно на самом деле работает */
.ombox .mbox-textsmall-div {
font-size: 90%;
}
@media (min-width: 720px) {
.ombox {
margin: 4px 10%;
}
.ombox.mbox-small {
/* @noflip */
clear: right;
/* @noflip */
float: right;
/* @noflip */
margin: 4px 0 4px 1em;
width: 238px;
}
/* Стили нотификаций для ноутбуков */
@media (max-width: 1366px) {
.ombox {
margin-left: 6%;
margin-right: 6%;
}
}
}
/* [[Категория:Модули:Подстраницы CSS]] */
6627874170f6674674bfa5796b2f7dfb6698cd81
Шаблон:Doc/begin
10
83
163
2024-06-30T22:14:58Z
wikipedia:ru>Putnik
0
[[ВП:×|отмена]] правки 138443392 участника [[Special:Contribs/Putnik|Putnik]] ([[UT:Putnik|обс.]])
wikitext
text/x-wiki
<includeonly><templatestyles src="Шаблон:Doc/styles.css" />
<div class="ts-doc-doc" id="doc">
<div class="ts-doc-header" id="Документация">
<div class="ts-doc-heading">Документация</div>
{{#if: {{{inline|}}} || {{Действия для страницы|lc={{{1}}}|nowatch=yes}} }}
</div>
<div class="ts-doc-content"></includeonly><noinclude>
{{doc}}
</noinclude>
c753f0a9f65d86707cdffaf93fb49c2c52daf92b
Шаблон:Музыкант/doc
10
106
209
2024-08-02T08:26:36Z
wikipedia:ru>Putnik
0
/* Примеры использования */ поддержка тёмной темы
wikitext
text/x-wiki
{{docpage}}{{OnLua|partly=1|module1=Wikidata/Interproject|module2=CategoryForProfession}}
{{Установлена проверка на неизвестные параметры}}
[[Википедия:Шаблоны-карточки|Шаблон-карточка]] {{tl|Музыкант}} должен присутствовать в начале статей о певцах, композиторах, дирижёрах и других музыкальных деятелях. Для музыкальных коллективов есть специальный шаблон {{tl|Музыкальный коллектив}}.
== Использование ==
{{Parameter names example|Фон|Имя|Оригинал имени|Изображение|Ширина|Описание изображения|Имя при рождении|Полное имя|Дата рождения|Место рождения|Дата смерти|Место смерти|Похоронен|Страна|Профессии|Годы активности|Певческий голос|Инструменты|Жанры|Псевдонимы|Коллективы|Лейбл текст|Лейблы|Награды|Логотип|Ширина логотипа|Сайт}}
{{Заготовка шаблона|$Оригинал имени = <nowiki>{{lang-XX|}}</nowiki>}}
== Описание параметров ==
# <code>Фон</code> — специализация, наиболее отражающая деятельность персоналии (см. подробности в {{tl|Музыкант/цвет}}):
::: {{Легенда|#f0e68c|'''вокалист''' — вокалист}}
::: {{Легенда|#f4bf92|'''инструменталист''' — музыкант, играющий на инструментах, но не поющий}}
::: {{Легенда|#bfe0bf|'''композитор''' — музыкант, не поющий и не играющий на инструментах (синонимы: '''дирижёр''', '''продюсер''')}}
# <code>Имя</code> — имя музыканта на русском языке.
# <code>Оригинал имени</code> — имя на официальном языке страны рождения в формате <code><nowiki>{{lang-код языка|имя}}</nowiki></code> (для русского языка — заполнять не следует).
# <code>Изображение</code> — имя файла с фотографией музыканта (см. ''[[Википедия:Иллюстрирование]]'').
# <code>Ширина</code> — ширина фото (обычно нет причины это менять).
# <code>Описание изображения</code> — где и когда сделано фото. Не сто́ит дублировать в этом поле имя музыканта: если о фотографии ничего не известно, просто не заполняйте это поле.
# <li value=7> <code>Имя при рождении</code> — следует заполнять в случае, если имя музыканта, указанное в параметре <code>Имя</code>, не принадлежало ему с рождения. Для указания полного имени нужно использовать поле <code>Полное имя</code> (''см. ниже'').</li>
# <code>Полное имя</code> — полное имя музыканта, если в поле <code>Имя</code> используется сокращённое имя.
# <code>Дата рождения</code> — дата рождения музыканта в формате дд.мм.гггг — например, <code><nowiki>31.12.1945</nowiki></code>.
# <code>Место рождения</code> — место рождения музыканта — например, <code><nowiki>{{МестоРождения|Лондон}}</nowiki></code>. Можно использовать шаблон {{tl|МестоРождения}}.
# <code>Дата смерти</code> — дата смерти музыканта в формате дд.мм.гггг (для ныне живущих, естественно, не заполняется). О датах по старому стилю см. примечание ниже.
# <code>Место смерти</code> — место смерти музыканта. Можно использовать шаблон {{tl|МестоСмерти}}.
# <code>Похоронен</code> — место захоронения музыканта.
# <code>Страна</code> — гражданство исполнителя; указывается просто название страны, без каких-либо шаблонов.
# <code>Профессии</code> — сферы музыкальной деятельности — например, <code><nowiki>{{певец|России|XX века|XXI века}}</nowiki></code>, <code><nowiki>{{поэт|России|XX века|XXI века}}</nowiki></code>
# <code>Годы активности</code> — годы активности музыканта.
# <code>Певческий голос</code> — Заполняется для оперных певцов и певиц. см. [[Певческие голоса]].
# <code>Инструменты</code> — основные музыкальные инструменты (для инструменталистов).
# <code>Жанры</code> — основные [[Список музыкальных жанров, направлений и стилей|жанры]], в которых пел/играл музыкант.
# <code>Псевдонимы</code> — [[псевдоним]]ы, под которыми известен музыкант.
# <code>Коллективы</code> — коллективы, в которых музыкант принимал участие.
# <code>Лейблы</code> — названия [[Лейбл звукозаписи|лейблов]], где издавался музыкант.
# <code>Награды</code> — государственные награды, имеющиеся у музыканта.
# <code>Логотип</code> — личный логотип музыканта (не группы, в которую он входит).
# <code>Ширина логотипа</code> — ширина логотипа (обычно нет причины это менять).
# <code>Сайт</code> — ссылка на официальный сайт музыканта.
=== Примечания ===
# Незаполненные поля не отображаются при выводе шаблона. Те из них, которые в принципе не могут быть заполнены (например, <code>Певческий голос</code> для не-певцов), нужно стирать.
# Если возникла необходимость изменить стандартные размеры фотографии, используйте параметр <code>Ширина</code>. Например, <code>{{nobr|1=Ширина = 250пкс}}</code>. Не рекомендуется использовать значения выше 300
# Шаблон автоматически добавляет включающую его статью в категории «{{cl|Музыканты по алфавиту}}» и «{{cl|Персоналии по алфавиту}}».
# Если в статье речь идёт об анонимном музыканте, известном только под псевдонимом, то в поля <code>Имя</code> записывается псевдоним.
# {{Старый-новый стиль,примечание}}
== Примеры использования ==
{| style="background: transparent; color: inherit"
|- valign="top"
|
{{Музыкант
| Имя = Иоганн Себастьян Бах
| Оригинал имени = {{lang-de|Johann Sebastian Bach}}
| Изображение = JSBach.jpg
| Описание изображения = Портрет Баха (1748)
| Фон = композитор
| Дата рождения = 21.03.1685
| Место рождения = [[Айзенах]]
| Дата смерти = 28.07.1750
| Место смерти = [[Лейпциг]]
| Страна = {{Флагификация|Германия}}
| Профессии = [[композитор]], [[органист]]
| Инструменты = [[Орган (музыкальный инструмент)|орга́н]]
| Жанры = [[классическая музыка]]
}}
|
{{Музыкант
| Имя = Джон Андерсон
| Оригинал имени = {{lang-en|Jon Anderson}}
| Изображение = Jon anderson 1977.jpg
| Описание изображения = На концерте [[Yes (группа)|Yes]] в [[Индианаполис]]е ([[1977 в музыке|1977]])
| Фон = вокалист
| Полное имя = Джон Рой Андерсон
| Дата рождения = 25.10.1944
| Место рождения = [[Аккрингтон]], [[Ланкашир]], [[Англия]]
| Страна = {{Флагификация|Великобритания}}
| Профессии = [[певец]], [[музыкант]]
| Жанры = [[прогрессивный рок]], [[нью-эйдж]]
| Коллективы = [[Yes (группа)|Yes]], [[Anderson Bruford Wakeman Howe|ABWH]], [[Jon & Vangelis]]
| Сайт = jonanderson.com
}}
|
{{Музыкант
| Имя = Джимми Пэйдж
| Оригинал имени = {{lang-en|Jimmy Page}}
| Изображение = Джимми Пэйдж.jpg
| Фон = инструменталист
| Полное имя = James Patrick Page
| Дата рождения = 09.01.1944
| Место рождения = Хестон, [[Лондон]], [[Англия]]
| Страна = {{Флагификация|Великобритания}}
| Профессии =
* [[Гитарист]]
* [[Музыкальный продюсер|продюсер]]
| Инструменты = [[Gibson Les Paul]]
* [[Gibson EDS-1275]]
* [[Danelectro 59 DC]]
* [[Fender Telecaster]]
| Жанры =
* [[хард-рок]]
* [[блюз-рок]]
* [[фолк-рок]]
* [[Прогрессивный рок|прогрессив]]
* [[хэви-метал]]
| Псевдонимы = ZoSo
| Коллективы =
* [[The Yardbirds]]
* [[Led Zeppelin]]
* [[The Honeydrippers]]
* [[The Firm]]
* [[Coverdale-Page]]
* [[Page and Plant]]
* [[XYZ (группа)|XYZ]]
| Лейблы =
* [[Swan Song]]
* [[Atlantic Records]]
| Сайт = jimmypageonline.com
}}
|}
== TemplateData ==
<templatedata>
{
"description": "Карточка для статей о певцах, композиторах, дирижёрах и других музыкальных деятелях",
"params": {
"Страна": {
"label": "Страна",
"description": "Гражданство музыканта. Указывается просто название страны, без каких-либо шаблонов; если стран несколько, они перечисляются через запятую. Может подставляться из Викиданных.",
"type": "content"
},
"Фон": {
"label": "Фон",
"description": "Цвет фона карточки. Допустимые значения: «вокалист» — вокалист; «инструменталист» — музыкант, играющий на инструментах, но не поющий; «композитор» — музыкант, не поющий и не играющий на инструментах (синонимы: «дирижёр», «продюсер»).",
"type": "line",
"suggestedvalues": [
"вокалист",
"инструменталист",
"композитор",
"дирижёр",
"продюсер"
]
},
"Имя": {
"label": "Имя",
"description": "Имя музыканта на русском языке. Если в статье речь идёт об анонимном музыканте, известном только под псевдонимом, то в поля «Имя» записывается псевдоним.",
"type": "string",
"default": "Название страницы",
"required": true
},
"Оригинал имени": {
"label": "Оригинал имени",
"description": "Имя музыканта на официальном языке страны рождения, если отличается от языка в заголовке карточки. Оборачивается в один из языковых шаблонов {{lang-XX}}.",
"example": "{{lang-de|Johann Sebastian Bach}}",
"type": "content"
},
"Изображение": {
"label": "Изображение",
"description": "Имя файла с фотографией музыканта. Может подставляться из Викиданных.",
"type": "wiki-file-name"
},
"Ширина": {
"label": "Ширина",
"description": "Ширина изображения. Не рекомендуется использовать значения выше 300.",
"type": "number"
},
"Описание изображения": {
"label": "Описание изображения",
"description": "Подпись к изображению, например где и когда сделано фото.",
"type": "line"
},
"Имя при рождении": {
"label": "Имя при рождении",
"description": "Следует заполнять в случае, если имя музыканта, указанное в параметре «Имя», не принадлежало ему с рождения.",
"type": "content"
},
"Полное имя": {
"label": "Полное имя",
"description": "Полное имя музыканта, если в поле «Имя» используется сокращённое имя.",
"type": "content"
},
"Дата рождения": {
"label": "Дата рождения",
"description": "Дата рождения музыканта в формате дд.мм.гггг, например 31.12.1945. Может подставляться из Викиданных. О датах по старому стилю см. примечание ниже.",
"type": "date"
},
"Дата смерти": {
"label": "Дата смерти",
"description": "Дата смерти музыканта в формате дд.мм.гггг (для ныне живущих, естественно, не заполняется). Может подставляться из Викиданных.",
"type": "date"
},
"Место рождения": {
"label": "Место рождения",
"description": "Место рождения музыканта — например, {{Место рождения|Лондон}}. Можно использовать шаблон {{МестоРождения}}. Может подставляться из Викиданных.",
"type": "content"
},
"Место смерти": {
"label": "Место смерти",
"description": "Место смерти музыканта. Можно использовать шаблон {{МестоСмерти}}. Может подставляться из Викиданных.",
"type": "content"
},
"Профессии": {
"label": "Профессии",
"description": "Сферы музыкальной деятельности — например, {{певец|России|XX века|XXI века}}, {{поэт|России|XX века|XXI века}}. Может подставляться из Викиданных.",
"type": "content"
},
"Годы активности": {
"label": "Годы активности",
"description": " Годы активности музыканта.",
"type": "string",
"example": "1999—2005, 2006 — {{нв}}"
},
"Певческий голос": {
"label": "Певческий голос",
"description": "Заполняется для оперных певцов и певиц.",
"type": "content"
},
"Инструменты": {
"label": "Инструменты",
"description": "Основные музыкальные инструменты (для инструменталистов).",
"type": "content"
},
"Жанры": {
"label": "Жанры",
"description": "Основные жанры, в которых пел/играл музыкант.",
"type": "content"
},
"Псевдонимы": {
"label": "Псевдонимы",
"description": "Псевдонимы, под которыми известен музыкант.",
"type": "content"
},
"Коллективы": {
"label": "Коллективы",
"description": "Коллективы, в которых музыкант принимал участие.",
"type": "content"
},
"Лейбл текст": {
"label": "Лейбл текст",
"description": "Подменяет название строки «Лейблы» на указанное.",
"type": "string"
},
"Лейблы": {
"label": "Лейблы",
"description": "Названия лейблов, где издавался музыкант.",
"type": "string"
},
"Награды": {
"label": "Награды",
"description": "Государственные награды, имеющиеся у музыканта.",
"type": "unbalanced-wikitext"
},
"Логотип": {
"label": "Логотип",
"description": "Имя файла с логотипом музыканта (не группы, в которую он входит). Может подставляться из Викиданных.",
"type": "wiki-file-name"
},
"Ширина логотипа": {
"label": "Ширина логотипа",
"description": "Ширина логотипа. Не рекомендуется использовать значения выше 300.",
"type": "number"
},
"Сайт": {
"label": "Сайт",
"description": "Ссылка на официальный сайт музыканта. Может подставляться из Викиданных.",
"type": "url"
},
"Викисклад": {
"label": "Викисклад",
"description": "Ссылка на категорию о музыканте на Викискладе. Может подставляться из Викиданных.",
"type": "line",
"deprecated": "Заполняется автоматически из Викиданных"
},
"Викитека": {
"label": "Викитека",
"type": "string",
"deprecated": "Заполнятся автоматически из Викиданных"
},
"Похоронен": {
"description": "Место, где похоронен музыкант.",
"type": "line"
},
"from": {
"type": "line"
},
"nocat": {
"type": "boolean",
"autovalue": "1"
}
},
"format": "{{_\n| ________________ = _\n}}\n",
"paramOrder": [
"Фон",
"Имя",
"Оригинал имени",
"Изображение",
"Ширина",
"Описание изображения",
"Имя при рождении",
"Полное имя",
"Дата рождения",
"Место рождения",
"Дата смерти",
"Место смерти",
"Похоронен",
"Страна",
"Профессии",
"Годы активности",
"Певческий голос",
"Инструменты",
"Жанры",
"Псевдонимы",
"Коллективы",
"Лейбл текст",
"Лейблы",
"Награды",
"Логотип",
"Ширина логотипа",
"Сайт",
"Викисклад",
"Викитека",
"from",
"nocat"
]
}
</templatedata>
== См. также ==
* {{tl|Музыкальный коллектив}}
* {{tl|Навигационная таблица музыкального исполнителя}}
* {{cl|Шаблоны-карточки:Личности|1}}
<includeonly>
[[Категория:Шаблоны:Музыканты]]
[[Категория:Шаблоны-карточки:Профессии культуры и искусства]]
[[Категория:Шаблоны-карточки:Музыка]]
</includeonly>
14ba03f3c4d9c6ee2c17a8274508fb62ce0dfa32
Шаблон:Doc/styles.css
10
84
165
2024-08-05T07:09:06Z
wikipedia:ru>Putnik
0
исправление кода для тёмной темы ([[phab:T369874]])
text
text/plain
.ts-doc-doc {
background-color: var(--background-color-progressive-subtle, #eaf3ff);
border: 1px solid var(--border-color-content-added, #afb6e9);
clear: both;
margin-top: 1em;
}
/* Ctrl+F ":target" in [[MediaWiki:Common.css]] */
.ts-doc-doc sup.reference:target,
.ts-doc-doc ol.references li:target,
.ts-doc-doc .highlight-target:target,
.ts-doc-doc cite:target,
.ts-doc-doc span.citation:target {
background: var(--ruwiki-background-color-blue200, #cfe3ff);
}
.ts-doc-header {
align-items: center;
background: var(--ruwiki-background-color-blue200, #cfe3ff);
display: flex;
flex-wrap: wrap;
padding: .642857em 1em .5em;
overflow: hidden;
}
.ts-doc-header .ts-tlinks-tlinks {
margin-left: auto;
}
.ts-doc-content {
padding: .214286em 1em;
}
.ts-doc-content:after {
content: '';
clear: both;
display: block;
}
.ts-doc-heading {
display: inline-block;
padding-left: 2em;
background: url(//upload.wikimedia.org/wikipedia/commons/c/ca/OOjs_UI_icon_info.svg) center left no-repeat;
background-size: contain;
font-size: small;
min-height: 1.75em;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
}
@media screen {
html.skin-theme-clientpref-night .ts-doc-heading {
background-image: url(//upload.wikimedia.org/wikipedia/commons/c/c0/OOjs_UI_icon_info-invert.svg);
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .ts-doc-heading {
background-image: url(//upload.wikimedia.org/wikipedia/commons/c/c0/OOjs_UI_icon_info-invert.svg);
}
}
.ts-doc-content > *:first-child,
.ts-doc-footer > *:first-child {
margin-top: .5em;
}
.ts-doc-content > *:last-child,
.ts-doc-footer > *:last-child {
margin-bottom: .5em;
}
.ts-doc-footer {
background-color: var(--background-color-progressive-subtle, #eaf3ff);
border: 1px solid var(--border-color-content-added, #afb6e9);
padding: .214286em 1em;
margin-top: .214286em;
margin-bottom: .214286em;
font-style: italic;
}
@media (max-width: 719px) {
.ts-doc-header {
display: block;
}
.ts-doc-header .ts-tlinks-tlinks {
float: none;
}
}
/* [[Категория:Шаблоны:Подстраницы CSS]] */
be8d912472a37a6051bee114da86f913839e7ca0
Шаблон:Цвет/Инструменталист.css
10
97
191
2024-08-19T15:46:13Z
wikipedia:ru>Putnik
0
поддержка тёмной темы — выбран цвет, имеющий контрастность выше 4.5 с #6d8af2, цветом ссылок на сайт и Викисклад; в связи с этим ограничения для Минервы больше не нужны
text
text/plain
.infobox-above,
.infobox-header,
.infobox-below {
background: #f4bf92;
}
@media screen {
html.skin-theme-clientpref-night .infobox-above,
html.skin-theme-clientpref-night .infobox-header,
html.skin-theme-clientpref-night .infobox-below {
background: #3f200f;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox-above,
html.skin-theme-clientpref-os .infobox-header,
html.skin-theme-clientpref-os .infobox-below {
background: #3f200f;
}
}
/*
[[Категория:Шаблоны:Подстраницы CSS]]
[[Категория:Шаблоны:Цвета по темам:Музыка|Инструменталист.css]]
*/
face7b56fa576807b9a51c764a3ac3b0f878ec82
Шаблон:Цвет/Вокалист.css
10
78
153
2024-08-19T15:50:07Z
wikipedia:ru>Putnik
0
отодвинем цвет дальше в жёлто-зелёную гамму, чтобы было заметно отличие от [[Шаблон:Цвет/Инструменталист.css]]
text
text/plain
.infobox-above,
.infobox-header,
.infobox-below {
background: #f0e68c;
}
@media screen {
html.skin-theme-clientpref-night .infobox-above,
html.skin-theme-clientpref-night .infobox-header,
html.skin-theme-clientpref-night .infobox-below {
background: #302a00;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox-above,
html.skin-theme-clientpref-os .infobox-header,
html.skin-theme-clientpref-os .infobox-below {
background: #302a00;
}
}
/*
[[Категория:Шаблоны:Подстраницы CSS]]
[[Категория:Шаблоны:Цвета по темам:Музыка|Вокалист.css]]
*/
2e2ee1ff27b701bb561598af95c43d81a92319bc
Модуль:Message box/configuration
828
17
31
2024-08-29T15:57:44Z
wikipedia:ru>Putnik
0
замена notheme на стили тёмной темы для cmbox
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Message box configuration --
-- --
-- This module contains configuration data for [[Module:Message box]]. --
--------------------------------------------------------------------------------
return {
ambox = {
types = {
speedy = {
class = 'ambox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'ambox-delete',
image = 'Stop hand nuvola.svg'
},
content = {
class = 'ambox-content',
image = 'Emblem-important.svg'
},
style = {
class = 'ambox-style',
image = 'Broom_icon.svg'
},
move = {
class = 'ambox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'ambox-protection',
image = 'Padlock-silver-medium.svg'
},
notice = {
class = 'ambox-notice',
image = 'Information.svg'
},
good = {
class = 'ambox-good',
image = 'Green star boxed.svg'
},
serious = {
class = 'ambox-serious',
image = 'Stop hand nuvola.svg'
},
merge = {
class = 'ambox-merge',
image = 'Merge-split-transwiki default.svg'
},
discussion = {
class = 'ambox-discussion',
image = 'Nuvola apps ksirc.png'
}
},
default = 'notice',
allowBlankParams = {'talk', 'sect', 'date', 'issue', 'fix', 'subst', 'hidden', 'image'},
allowSmall = true,
smallParam = 'left',
smallClass = 'mbox-small-left',
substCheck = true,
classes = {'metadata', 'ambox'},
imageEmptyCell = true,
imageCheckBlank = true,
imageSmallSize = '20x20px',
imageCellDiv = true,
useCollapsibleTextFields = true,
imageRightNone = true,
sectionDefault = 'статья',
allowMainspaceCategories = true,
templateCategory = 'Шаблоны:Шаблоны-сообщения для статей',
templateCategoryRequireName = true,
templateErrorCategory = 'Шаблоны:Шаблоны-сообщения для статей с пропущенными параметрами',
templateErrorParamsToCheck = {'issue', 'fix'},
removalNotice = '[[Help:Maintenance template removal|Learn how and when to remove this template message]]',
templatestyles = 'Module:Message box/ambox.css',
},
cmbox = {
types = {
speedy = {
class = 'cmbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'cmbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'cmbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'cmbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'cmbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'cmbox-protection',
image = 'Padlock-silver-medium.svg'
},
notice = {
class = 'cmbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'cmbox'},
imageEmptyCell = true,
useCollapsibleTextFields = true,
templatestyles = 'Module:Message box/cmbox.css',
},
fmbox = {
types = {
warning = {
class = 'fmbox-warning',
image = 'Ambox warning pn.svg'
},
editnotice = {
class = 'fmbox-editnotice',
image = 'Information icon4.svg'
},
system = {
class = 'fmbox-system',
image = 'Information icon4.svg'
}
},
default = 'system',
showInvalidTypeError = true,
classes = {'fmbox'},
imageEmptyCell = false,
imageRightNone = false,
useCollapsibleTextFields = true,
templatestyles = 'Module:Message box/fmbox.css',
},
imbox = {
types = {
speedy = {
class = 'imbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'imbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'imbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'imbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'imbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'imbox-protection',
image = 'Padlock-silver-medium.svg'
},
license = {
class = 'imbox-license licensetpl',
image = 'Imbox license.png' -- @todo We need an SVG version of this
},
featured = {
class = 'imbox-featured',
image = 'Cscr-featured.svg'
},
notice = {
class = 'imbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'imbox'},
imageEmptyCell = true,
below = true,
useCollapsibleTextFields = true,
templateCategory = 'Шаблоны:Шаблоны-сообщения для файлов',
templatestyles = 'Module:Message box/imbox.css',
},
ombox = {
types = {
speedy = {
class = 'ombox-speedy',
image = 'OOjs UI icon alert-destructive.svg'
},
delete = {
class = 'ombox-delete',
image = 'OOjs UI icon alert-destructive.svg'
},
content = {
class = 'ombox-content',
image = 'OOjs UI icon notice-warning.svg'
},
style = {
class = 'ombox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'ombox-move',
image = 'Imbox move.png'
},
protection = {
class = 'ombox-protection',
image = 'Imbox protection.png'
},
notice = {
class = 'ombox-notice',
image = 'OOjs UI icon info-progressive.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'ombox'},
allowSmall = true,
imageEmptyCell = true,
imageRightNone = true,
useCollapsibleTextFields = true,
templatestyles = 'Module:Message box/ombox.css',
},
tmbox = {
types = {
speedy = {
class = 'tmbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'tmbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'tmbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'tmbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'tmbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'tmbox-protection',
image = 'Padlock-silver-medium.svg'
},
notice = {
class = 'tmbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'tmbox'},
allowSmall = true,
imageRightNone = true,
imageEmptyCell = true,
imageEmptyCellStyle = true,
useCollapsibleTextFields = true,
templateCategory = 'Шаблоны:Шаблоны-сообщения для страниц обсуждений',
templatestyles = 'Module:Message box/tmbox.css',
}
}
2c0750ec1561e8ec25c0988c411f3c69e4957483
Модуль:Check for unknown parameters
828
9
15
2024-09-19T19:18:15Z
wikipedia:ru>Stjn
0
поддержка тёмной темы
Scribunto
text/plain
-- This module may be used to compare the arguments passed to the parent
-- with a list of arguments, returning a specified result if an argument is
-- not on the list
local p = {}
local function trim(s)
return s:match('^%s*(.-)%s*$')
end
local function isnotempty(s)
return s and trim(s) ~= ''
end
function p.check (frame)
local args = frame.args
local pargs = frame:getParent().args
local ignoreblank = isnotempty(frame.args['ignoreblank'])
local showblankpos = isnotempty(frame.args['showblankpositional'])
local knownargs = {}
local unknown = frame.args['unknown'] or 'Found _VALUE_, '
local preview = frame.args['preview']
local values = {}
local res = {}
local regexps = {}
-- create the list of known args, regular expressions, and the return string
for k, v in pairs(args) do
if type(k) == 'number' then
v = trim(v)
knownargs[v] = 1
elseif k:find('^regexp[1-9][0-9]*$') then
table.insert(regexps, '^' .. v .. '$')
end
end
if isnotempty(preview) then
preview = '<div class="hatnote" style="color: var(--color-error, #d73333)"><strong>Предупреждение:</strong> '
.. preview
.. ' (это сообщение видно только при предпросмотре страницы).</div>'
elseif preview == nil then
preview = unknown
end
-- loop over the parent args, and make sure they are on the list
for k, v in pairs(pargs) do
if type(k) == 'string' and knownargs[k] == nil then
local knownflag = false
for i, regexp in ipairs(regexps) do
if mw.ustring.match(k, regexp) then
knownflag = true
break
end
end
if not knownflag and ( not ignoreblank or isnotempty(v) ) then
k = mw.ustring.gsub(k, '[^%w\-_ ]', '?')
table.insert(values, k)
end
elseif type(k) == 'number' and
knownargs[tostring(k)] == nil and
( showblankpos or isnotempty(v) )
then
local vlen = mw.ustring.len(v)
v = mw.ustring.sub(v, 1, (vlen < 25) and vlen or 25)
v = mw.ustring.gsub(v, '[^%w\-_ ]', '?')
table.insert(values, k .. ' = ' .. v .. ((vlen >= 25) and ' ...' or ''))
end
end
-- add resuls to the output tables
if #values > 0 then
if frame:preprocess( "{{REVISIONID}}" ) == "" then
unknown = preview
end
for k, v in pairs(values) do
if v == '' then
-- Fix odd bug for | = which gets stripped to the empty string and
-- breaks category links
v = ' '
end
local r = unknown:gsub('_VALUE_', v)
table.insert(res, r)
end
end
return table.concat(res)
end
function p.generate (frame)
local res = '{{#invoke:check for unknown parameters|check\n' ..
'|unknown=' .. frame.args['unknown'] .. '\n'
local checkerparams = {'ignoreblank', 'preview', 'showblankpositional'}
for _, v in pairs(checkerparams) do
if frame.args[v] then
res = res .. '|' .. v .. '=' .. frame.args[v] .. '\n'
end
end
local templatenamespace = frame.args[1]
local templatetitle = frame.args[2]
local pagepointer = mw.title.new(templatetitle, templatenamespace) -- именно такой порядок!
local text = pagepointer.getContent(pagepointer)
local params = {}
for param in string.gmatch(text, '\{\{\{([^\|\}]*)') do
params[#params+1] = mw.text.trim(param)
end
table.sort(params)
for k, v in pairs(params) do
if k == 1 or v ~= params[k-1] then
res = res .. '|' .. v
end
end
res = res .. '}}'
return res
end
return p
9da4c0ae23797bb024279d7544e897ae3f2bbf43
Шаблон:Docpage
10
93
183
2024-09-25T09:40:06Z
wikipedia:ru>Stjn
0
__EXPECTED_UNCONNECTED_PAGE__
wikitext
text/x-wiki
<includeonly>{{#ifeq: {{SUBPAGENAME}} | doc
| {{fmbox
| class = hlist nowraplinks
| style = margin-bottom:1em; background:var(--background-color-progressive-subtle, #eaf3ff); color:inherit; border:1px solid var(--border-color-content-added, #a3d3ff);
| image = [[Файл:OOjs UI icon info.svg|24px|link=|alt=|class=skin-invert-image]]
| text = <div>
* [[:{{#titleparts: {{SUBJECTPAGENAME}} | -1 }}]]
* [[:{{SUBJECTPAGENAME}}|Документация]]
* [[{{#titleparts: {{TALKPAGENAME}} | -1 }}|Обсуждение]]
* [[Служебная:Whatlinkshere/{{#titleparts: {{SUBJECTPAGENAME}} | -1 }}|Где используется]] {{#ifeq: {{NAMESPACE}} | {{ns:Template}} |
** {{Параметры шаблона|{{#titleparts: {{PAGENAME}} | -1 }}}}
}}</div><!--
-->{{#if: {{{nocat|}}} || {{#ifexist: {{NAMESPACE}}:{{BASEPAGENAME}} || [[Категория:Шаблоны:Документация несуществующих шаблонов]] }} }}
}}{{#if: {{{nocat|}}} || {{#ifeq: {{NAMESPACE}}
| Модуль
| [[Категория:Модули:Документация]]
| [[Категория:Шаблоны:Документация]]
}}__EXPECTED_UNCONNECTED_PAGE__
}}
}}</includeonly><noinclude>{{doc}}</noinclude>
e2d07566c50be35ac409e8396893a3b9d8676e0c
Шаблон:Вложенные кавычки
10
89
175
2024-10-12T20:37:27Z
wikipedia:ru>Stjn
0
перевод на [[модуль:Вложенные кавычки]]
wikitext
text/x-wiki
{{safesubst:<noinclude />#invoke:Вложенные кавычки|main}}<noinclude>
{{doc}}
</noinclude>
9ad9d29329e774649043f48fba384679babb4c08
Модуль:Вложенные кавычки
828
113
223
2024-10-12T23:33:31Z
wikipedia:ru>Stjn
0
require( 'strict' )
Scribunto
text/plain
--
-- Re-implement [[Template:Вложенные кавычки]] in Lua
-- Replaces «» to „“ without touching links
--
require( 'strict' )
local getArgs
local p = {}
local function isEmpty( str )
return str == nil or str == ''
end
local function protectLinks( str )
local links, head = {}, 0
while true do
local s, e, link = str:find( '(%[%[.-%]%])', head )
if not link then
return str, links
elseif link:find( '[[', 3, true ) then
head = s + 2
else
-- If the alt text contains '[', it can have one final ']'.
if link:match( '^[^|]*|.-%[', 3 ) and str:sub( e + 1, e + 1 ) == ']' then
link = link .. ']'
end
table.insert( links, link )
local placeholder = mw.ustring.char( 0xF0000 + #links )
str = str:gsub( link:gsub( '[$%%()*+%-.?[%]^]', '%%%0' ), placeholder )
head = str:find( placeholder ) + 1
end
end
end
local function unprotectLinks( str, links )
for i, link in ipairs( links ) do
str = str:gsub( mw.ustring.char( 0xF0000 + i ), link:gsub( '%%', '%%%%' ), 1 )
end
return str
end
local function replace( str )
if isEmpty( str ) then
return ''
end
str = mw.ustring.gsub( str, '«(.[^«»]-)»', '„%1“' )
return str
end
function p._main( text )
if isEmpty( text ) then
return ''
end
local links = {}
text, links = protectLinks( text )
if #links == 0 then
return replace( text )
end
-- Replace visible link text while keeping links intact
for i, link in ipairs( links ) do
local linkTarget = mw.text.trim( link, '%[%]' )
local linkText = ''
local pipePos = link:find( '|', 1, true )
if pipePos ~= nil then
local parts = mw.text.split( linkTarget, '|' )
linkTarget = parts[ 1 ]
linkText = replace( parts[ 2 ] )
else
linkText = replace( linkTarget )
end
links[ i ] = string.format( '[[%s|%s]]', linkTarget, linkText )
end
text = replace( text )
text = unprotectLinks( text, links )
return text
end
function p.main( frame )
getArgs = require( 'Module:Arguments' ).getArgs
local args = getArgs( frame )
return p._main( args[ 1 ] )
end
return p
e7cf7cd583a5fa189c85ccf455feebd48aa60fa0
Модуль:Wikidata
828
31
59
2024-10-26T15:17:47Z
wikipedia:ru>Stjn
0
[[ВП:×|отмена]]: сломало отображение в множестве статей
Scribunto
text/plain
---settings, may differ from project to project
local fileDefaultSize = '267x400px'
local outputReferences = true
local writingSystemElementId = 'Q8209'
local langElementId = 'Q7737'
---Ссылки на используемые модули, которые потребуются в 99% случаев загрузки страниц (чтобы иметь на виду при переименовании)
local moduleSources = require( 'Module:Sources' )
local WDS = require( 'Module:WikidataSelectors' )
---Константы
---@type string
local CONTENT_LANGUAGE_CODE = mw.language.getContentLanguage():getCode()
local p = {}
local g_config, g_frame
local formatDatavalue, formatEntityId, formatRefs, formatSnak, formatStatement,
formatStatementDefault, getSourcingCircumstances, getPropertyParams
---@param obj table
---@param target table
---@param skipEmpty boolean | nil
---@return table
local function copyTo( obj, target, skipEmpty )
for key, val in pairs( obj ) do
if skipEmpty ~= true or ( val ~= nil and val ~= '' ) then
target[ key ] = val
end
end
return target
end
---@param prev number | nil
---@param next number | nil
---@return number | nil
local function min( prev, next )
if prev == nil or prev > next then
return next
end
return prev
end
---@param prev number | nil
---@param next number | nil
---@return number | nil
local function max( prev, next )
if prev == nil or prev < next then
return next
end
return prev
end
---@param section string
---@param code string
---@return any | nil
local function getConfig( section, code )
if g_config == nil then
g_config = require( 'Module:Wikidata/config' )
end
if not g_config then
g_config = {}
end
if not section then
return g_config
end
if not code then
return g_config[ section ] or {}
end
if not g_config[ section ] then
return nil
end
return g_config[ section ][ code ]
end
---@param code string
---@param sortKey string | nil
---@return string
local function getCategoryByCode( code, sortKey )
local value = getConfig( 'categories', code )
if not value or value == '' then
return ''
end
if sortKey ~= nil then
return '[[Category:' .. value .. '|' .. sortKey .. ']]'; -- экранировать?
else
return '[[Category:' .. value .. ']]'
end
end
---@param isoStr string | table
---@return table | nil
local function splitISO8601( isoStr )
if 'table' == type( isoStr ) then
if isoStr.args and isoStr.args[ 1 ] then
isoStr = '' .. isoStr.args[ 1 ]
else
return 'unknown argument type: ' .. type( isoStr ) .. ': ' .. table.tostring( isoStr )
end
end
local Y, M, D = ( function( str )
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local _Y, _M, _D = mw.ustring.match( str, pattern )
return tonumber( _Y ), tonumber( _M ), tonumber( _D )
end )( isoStr )
local h, m, s = ( function( str )
local pattern = "T(%d+):(%d+):(%d+)%Z"
local _H, _M, _S = mw.ustring.match( str, pattern )
return tonumber( _H ), tonumber( _M ), tonumber( _S )
end )( isoStr )
local oh, om = ( function( str )
if str:sub(-1) == "Z" then -- ends with Z, Zulu time
return 0, 0
end
-- matches ±hh:mm, ±hhmm or ±hh; else returns nils
local pattern = "([-+])(%d%d):?(%d?%d?)$"
local sign, oh, om = mw.ustring.match( str, pattern )
sign, oh, om = sign or "+", oh or "00", om or "00"
return tonumber( sign .. oh ), tonumber( sign .. om )
end )( isoStr )
return { year=Y, month=M, day=D, hour=( h + oh ), min=( m + om ), sec=s }
end
---Внутренняя функции для получения границ временного диапазона
---@param time string
---@param precision number
---@return table | nil
function p._parseTimeBoundaries( time, precision )
local s = splitISO8601( time )
if not s then
return nil
end
if precision >= 0 and precision <= 8 then
local powers = { 1000000000 , 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10 }
local power = powers[ precision + 1 ]
local left = s.year - ( s.year % power )
return { tonumber( os.time( { year=left, month=1, day=1, hour=0, min=0, sec=0 } ) ) * 1000,
tonumber( os.time( { year=left + power - 1, month=12, day=31, hour=29, min=59, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 9 then
return { tonumber( os.time( { year=s.year, month=1, day=1, hour=0, min=0, sec=0} )) * 1000,
tonumber( os.time( { year=s.year, month=12, day=31, hour=23, min=59, sec=58} )) * 1000 + 1999 }
end
if precision == 10 then
local lastDays = { 31, 28.25, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
local lastDay = lastDays[ s.month ]
return { tonumber( os.time( { year=s.year, month=s.month, day=1, hour=0, min=0, sec=0 } ) ) * 1000,
tonumber( os.time( { year=s.year, month=s.month, day=lastDay, hour=23, min=59, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 11 then
return { tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=0, min=0, sec=0 } ) ) * 1000,
tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=23, min=59, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 12 then
return { tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=0, sec=0 } ) ) * 1000,
tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=59, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 13 then
return { tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=s.min, sec=0 } ) ) * 1000,
tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=s.min, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 14 then
local t = tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=s.min, sec=0 } ) )
return { t * 1000, t * 1000 + 999 }
end
error( 'Unsupported precision: ' .. precision )
end
---Внутренняя функция для получения числового значения времени из snak'а
---@param table snak
---@return number | nil
function p._parseTimeFromSnak( snak )
if snak and snak.datavalue and snak.datavalue.value and snak.datavalue.value.time then
local timeData = splitISO8601( tostring( snak.datavalue.value.time ) )
timeData.month = math.max( timeData.month, 1 )
timeData.day = math.max( timeData.day, 1 )
return tonumber( os.time( timeData ) ) * 1000
end
return nil
end
---Функция для формирования категории на основе wikidata/config
---@param options table
---@param entityId string
---@return string
local function extractCategory( options, entityId )
if not entityId or not options.category or options.nocat then
return ''
end
if type( entityId ) ~= 'string' then
entityId = entityId.id
end
local claims = WDS.load( entityId, options.category )
if not claims then
return ''
end
for _, claim in pairs( claims ) do
if claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.type == 'wikibase-entityid'
then
local catEntityId = claim.mainsnak.datavalue.value.id
local wbStatus, catSiteLink = pcall( mw.wikibase.getSitelink, catEntityId )
if wbStatus and catSiteLink then
return '[[' .. catSiteLink .. ']]'
end
end
end
return ''
end
---Преобразует строку в булевое значение
---@param valueToParse string
---@return boolean Преобразованное значение, если его удалось распознать, или defaultValue во всех остальных случаях
local function toBoolean( valueToParse, defaultValue )
if valueToParse ~= nil then
if valueToParse == false or valueToParse == '' or valueToParse == 'false' or valueToParse == '0' then
return false
end
return true
end
return defaultValue
end
---Обрачивает отформатированное значение в инлайновый или блочный тег.
---@param value string value
---@param attributes table of attributes
---@return string HTML tag with value
local function wrapValue( value, attributes )
local tagName = 'span'
local spacer = ''
if string.match( value, '\n' )
or string.match( value, '<t[dhr][ >]' )
or string.match( value, '<div[ >]' )
or string.find( value, 'UNIQ%-%-imagemap' )
then
tagName = 'div'
spacer = '\n'
end
local attrString = ''
for key, val in pairs( attributes or {} ) do
local _key = mw.text.trim( key )
local _value = mw.text.encode( mw.text.trim( val ) )
attrString = attrString .. _key .. '="' .. _value .. '" '
end
return '<' .. tagName .. ' ' .. attrString .. '>' .. spacer .. value .. '</' .. tagName .. '>'
end
---Wraps formatted snak value into HTML tag with attributes.
---@param value string value of snak
---@param hash string
---@param attributes table of extra attributes
---@return string HTML tag with value
local function wrapSnak( value, hash, attributes )
local newAttributes = mw.clone( attributes or {} )
newAttributes[ 'class' ] = ( newAttributes[ 'class' ] or '' ) .. ' wikidata-snak'
if hash then
newAttributes[ 'data-wikidata-hash'] = hash
else
newAttributes[ 'class' ] = newAttributes[ 'class' ] .. ' wikidata-main-snak'
end
return wrapValue( value, newAttributes )
end
---Wraps formatted statement value into HTML tag with attributes.
---@param value string value of statement
---@param propertyId string PID of property
---@param claimId string ID of claim or nil for local value
---@param attributes table of extra attributes
---@return string HTML tag with value
local function wrapStatement( value, propertyId, claimId, attributes )
local newAttributes = mw.clone( attributes or {} )
newAttributes[ 'class' ] = newAttributes[ 'class' ] or ''
newAttributes[ 'data-wikidata-property-id' ] = string.upper( propertyId )
if claimId then
newAttributes[ 'class' ] = newAttributes[ 'class' ] .. ' wikidata-claim'
newAttributes[ 'data-wikidata-claim-id' ] = claimId
else
newAttributes[ 'class' ] = newAttributes[ 'class' ] .. ' no-wikidata'
end
return wrapValue( value, newAttributes )
end
---Wraps formatted qualifier's statement value into HTML tag with attributes.
---@param value string value of qualifier's statement
---@param qualifierId string PID of qualifier
---@param attributes table of extra attributes
---@return string HTML tag with value
local function wrapQualifier( value, qualifierId, attributes )
local newAttributes = mw.clone( attributes or {} )
newAttributes[ 'data-wikidata-qualifier-id' ] = string.upper( qualifierId )
return wrapValue( value, newAttributes )
end
---Функция для получения сущности (еntity) для текущей страницы
---Подробнее о сущностях см. d:Wikidata:Glossary/ru
---@param id string Идентификатор (типа P18, Q42)
---@return table Таблица, элементы которой индексируются с нуля
local function getEntityFromId( id )
local entity
local wbStatus
if id then
wbStatus, entity = pcall( mw.wikibase.getEntity, id )
else
wbStatus, entity = pcall( mw.wikibase.getEntity )
end
return entity
end
---Внутренняя функция для формирования сообщения об ошибке
---@param key string Ключ элемента в таблице config.errors (например entity-not-found)
---@return void
local function throwError( key )
error( getConfig( 'errors', key ) )
end
---Функция для получения идентификатора сущностей
---@param value table
---@return string
local function getEntityIdFromValue( value )
local prefix = ''
if value[ 'entity-type' ] == 'item' then
prefix = 'Q'
elseif value[ 'entity-type' ] == 'property' then
prefix = 'P'
else
throwError( 'unknown-entity-type' )
end
return prefix .. value[ 'numeric-id' ]
end
---Проверка на наличие специализированной функции в опциях
---@param options table
---@param prefix string
---@return function
local function getUserFunction( options, prefix, defaultFunction )
-- проверка на указание специализированных обработчиков в параметрах,
-- переданных при вызове
if options[ prefix .. '-module' ] or options[ prefix .. '-function' ] then
-- проверка на пустые строки в параметрах или их отсутствие
if not options[ prefix .. '-module' ] or not options[ prefix .. '-function' ] then
throwError( 'unknown-' .. prefix .. '-module' )
end
-- динамическая загруза модуля с обработчиком указанным в параметре
local formatter = require( 'Module:' .. options[ prefix .. '-module' ] )
if formatter == nil then
throwError( prefix .. '-module-not-found' )
end
local fun = formatter[ options[ prefix .. '-function' ] ]
if fun == nil then
throwError( prefix .. '-function-not-found' )
end
return fun
end
return defaultFunction
end
---Выбирает свойства по property id, дополнительно фильтруя их по рангу
---@param context table
---@param options table
---@param propertySelector string
---@return table | nil
local function selectClaims( context, options, propertySelector )
if not context then error( 'context not specified' ); end
if not options then error( 'options not specified' ); end
if not options.entityId then error( 'options.entity is missing' ); end
if not propertySelector then error( 'propertySelector not specified' ); end
local result = WDS.load( options.entityId, propertySelector )
if not result or #result == 0 then
return nil
end
if options.limit and options.limit ~= '' and options.limit ~= '-' then
local limit = tonumber( options.limit, 10 )
while #result > limit do
table.remove( result )
end
end
return result
end
---Функция для получения значения свойства элемента в заданный момент времени.
---@param entityId string
---@param boundaries table Временные границы
---@param propertyIds table<string>
---@param selectors table<string>
---@return table Таблица соответствующих значений свойства
local function getPropertyInBoundaries( context, entityId, boundaries, propertyIds, selectors )
if type( entityId ) ~= 'string' then error( 'type of entityId argument expected string, but was ' .. type(entityId)); end
local results = {}
if not propertyIds or #propertyIds == 0 then
return results
end
for i, propertyId in ipairs( propertyIds ) do
local selector
if selectors ~= nil then
selector = selectors[ i ] or selectors[ propertyId ] or propertyId
else
selector = propertyId
end
local fakeAllClaims = {}
fakeAllClaims[ propertyId ] = mw.wikibase.getAllStatements( entityId, propertyId )
local filteredClaims = WDS.filter( fakeAllClaims, selector .. '[rank:preferred, rank:normal]' )
if filteredClaims then
for _, claim in pairs( filteredClaims ) do
if not boundaries then
if not claim.qualifiers or not claim.qualifiers.P582 then
table.insert( results, claim.mainsnak )
end
else
local startBoundaries = p.getTimeBoundariesFromQualifier( context.frame, context, claim, 'P580' )
local endBoundaries = p.getTimeBoundariesFromQualifier( context.frame, context, claim, 'P582' )
if ( startBoundaries == nil or startBoundaries[ 1 ] <= boundaries[ 1 ] ) and
( endBoundaries == nil or endBoundaries[ 1 ] >= boundaries[ 2 ] )
then
table.insert( results, claim.mainsnak )
end
end
end
end
if #results > 0 then
break
end
end
return results
end
---@param context table
---@param propertyId string
---@return table | nil
function p.getTimeBoundariesFromProperty( context, propertyId )
local dateClaims = WDS.filter( context.entity.claims, propertyId )
if not dateClaims or #dateClaims == 0 then
return nil;
end
-- only support exact date so far, but need improvment
local left = nil
local right = nil
for _, claim in pairs( dateClaims ) do
if not claim.mainsnak then
return nil
end
local boundaries = context.parseTimeBoundariesFromSnak( claim.mainsnak )
if not boundaries then
return nil
end
left = min( left, boundaries[ 1 ] )
right = max( right, boundaries[ 2 ] )
end
if not left or not right then
return nil
end
return { left, right }
end
---@param context table
---@param propertyIds table<string>
---@return table | nil
function p.getTimeBoundariesFromProperties( context, propertyIds )
for _, propertyId in ipairs( propertyIds ) do
local result = p.getTimeBoundariesFromProperty( context, propertyId );
if result then
return result
end
end
return nil
end
---@param context table
---@param statement table
---@param qualifierId string
---@return table | nil
function p.getTimeBoundariesFromQualifier( _, context, statement, qualifierId )
-- only support exact date so far, but need improvement
local left, right
if statement.qualifiers and statement.qualifiers[ qualifierId ] then
for _, qualifier in pairs( statement.qualifiers[ qualifierId ] ) do
local boundaries = context.parseTimeBoundariesFromSnak( qualifier )
if not boundaries then
return nil
end
left = min( left, boundaries[ 1 ] )
right = max( right, boundaries[ 2 ] )
end
end
if not left or not right then
return nil
end
return { left, right }
end
---@param _ table
---@param context table
---@param statement table
---@param qualifierIds table<string>
---@return table | nil
function p.getTimeBoundariesFromQualifiers( _, context, statement, qualifierIds )
if not qualifierIds then
qualifierIds = { 'P582', 'P580', 'P585' }
end
for _, qualifierId in pairs( qualifierIds ) do
local result = p.getTimeBoundariesFromQualifier( _, context, statement, qualifierId )
if result then
return result
end
end
return nil
end
---@type table<string>
local getLabelWithLang_DEFAULT_PROPERTIES = { 'P1813', 'P1448', 'P1705' }
---@type table<string>
local getLabelWithLang_DEFAULT_SELECTORS = {
'P1813[language:' .. CONTENT_LANGUAGE_CODE .. '][!P282,P282:' .. writingSystemElementId .. '][!P3831,P3831:Q105690470]',
'P1448[language:' .. CONTENT_LANGUAGE_CODE .. '][!P282,P282:' .. writingSystemElementId .. '][!P3831,P3831:Q105690470]',
'P1705[language:' .. CONTENT_LANGUAGE_CODE .. '][!P282,P282:' .. writingSystemElementId .. '][!P3831,P3831:Q105690470]'
}
---Функция для получения метки элемента в заданный момент времени.
---@param context table
---@param options table
---@param entityId string
---@param boundaries table
---@param propertyIds table
---@param selectors table<string>
---@return string, string Текстовая метка элемента, язык метки
local function getLabelWithLang( context, options, entityId, boundaries, propertyIds, selectors )
if type( entityId ) ~= 'string' then error( 'type of entityId argument expected string, but was ' .. type( entityId ) ); end
if not entityId then
return nil
end
local langCode = CONTENT_LANGUAGE_CODE
-- name from label
local label
if options.text and options.text ~= '' then
label = options.text
else
if not propertyIds then
propertyIds = getLabelWithLang_DEFAULT_PROPERTIES
selectors = getLabelWithLang_DEFAULT_SELECTORS
end
-- name from properties
local results = getPropertyInBoundaries( context, entityId, boundaries, propertyIds, selectors )
for _, result in pairs( results ) do
if result.datavalue and result.datavalue.value then
if result.datavalue.type == 'monolingualtext' and result.datavalue.value.text then
label = result.datavalue.value.text
langCode = result.datavalue.value.language
break
elseif result.datavalue.type == 'string' then
label = result.datavalue.value
break
end
end
end
if not label then
label, langCode = mw.wikibase.getLabelWithLang( entityId )
if not langCode then
return nil
end
end
end
return label, langCode
end
---@param context table
---@param options table
---@return string
local function formatPropertyDefault( context, options )
if not context then error( 'context not specified' ); end
if not options then error( 'options not specified' ); end
if not options.entityId then error( 'options.entityId missing' ); end
local claims
if options.property then -- TODO: Почему тут может не быть property?
if options.rank then -- передать настройки ранга из конфига
claims = context.selectClaims( options, options.property .. options.rank )
else
claims = context.selectClaims( options, options.property )
end
end
if claims == nil then
return '' --TODO error?
end
-- Обход всех заявлений утверждения и с накоплением оформленных предпочтительных
-- заявлений в таблице
local formattedClaims = {}
for _, claim in pairs( claims ) do
local formattedStatement = context.formatStatement( options, claim )
-- здесь может вернуться либо оформленный текст заявления, либо строка ошибки, либо nil
if formattedStatement and formattedStatement ~= '' then
if not options.plain then
formattedStatement = context.wrapStatement( formattedStatement, options.property, claim.id )
end
table.insert( formattedClaims, formattedStatement )
end
end
-- создание текстовой строки со списком оформленых заявлений из таблицы
local out = mw.text.listToText( formattedClaims, options.separator, options.conjunction )
if out ~= '' then
if options.before then
out = options.before .. out
end
if options.after then
out = out .. options.after
end
end
return out
end
---Create context
---@param initOptions table
---@return table | nil
local function initContext( initOptions )
local context = {
entityId = initOptions.entityId,
entity = initOptions.entity,
extractCategory = extractCategory,
formatSnak = formatSnak,
formatPropertyDefault = formatPropertyDefault,
formatStatementDefault = formatStatementDefault,
getPropertyInBoundaries = getPropertyInBoundaries,
getTimeBoundariesFromProperty = p.getTimeBoundariesFromProperty,
getTimeBoundariesFromProperties = p.getTimeBoundariesFromProperties,
getTimeBoundariesFromQualifier = p.getTimeBoundariesFromQualifier,
getTimeBoundariesFromQualifiers = p.getTimeBoundariesFromQualifiers,
parseTimeFromSnak = p._parseTimeFromSnak,
getLabelWithLang = getLabelWithLang,
wrapSnak = wrapSnak,
wrapStatement = wrapStatement,
wrapQualifier = wrapQualifier,
}
context.cloneOptions = function( options )
local entity = options.entity
options.entity = nil
local newOptions = mw.clone( options )
options.entity = entity
newOptions.entity = entity
newOptions.frame = options.frame; -- На склонированном фрейме frame:expandTemplate()
return newOptions
end
context.formatProperty = function( options )
local func = getUserFunction( options, 'property', context.formatPropertyDefault )
return func( context, options )
end
context.formatStatement = function( options, statement ) return formatStatement( context, options, statement ) end
context.formatSnak = function( options, snak, circumstances ) return formatSnak( context, options, snak, circumstances ) end
context.formatRefs = function( options, statement ) return formatRefs( context, options, statement ) end
context.parseTimeBoundariesFromSnak = function( snak )
if snak and snak.datavalue and snak.datavalue.value and snak.datavalue.value.time and snak.datavalue.value.precision then
return p._parseTimeBoundaries( snak.datavalue.value.time, snak.datavalue.value.precision )
end
return nil
end
context.getSourcingCircumstances = function( statement )
return getSourcingCircumstances( statement )
end
context.selectClaims = function( options, propertyId )
return selectClaims( context, options, propertyId )
end
return context
end
---Функция для оформления утверждений (statement)
---Подробнее о утверждениях см. d:Wikidata:Glossary/ru
---@param options table
---@return string Formatted wikitext.
local function formatProperty( options )
-- Получение сущности по идентификатору
local entity = getEntityFromId( options.entityId )
if not entity then
return -- throwError( 'entity-not-found' )
end
-- проверка на присутсвие у сущности заявлений (claim)
-- подробнее о заявлениях см. d:Викиданные:Глоссарий
if not entity.claims then
return '' --TODO error?
end
-- improve options
options.frame = g_frame
options.entity = entity
options.extends = function( self, newOptions )
return copyTo( newOptions, copyTo( self, {} ) )
end
if options.i18n then
options.i18n = copyTo( options.i18n, copyTo( getConfig( 'i18n' ), {} ) )
else
options.i18n = getConfig( 'i18n' )
end
local context = initContext( options )
return context.formatProperty( options )
end
---Функция для оформления одного утверждения (statement)
---@param context table
---@param options table
---@param statement table
---@return string Formatted wikitext.
function formatStatement( context, options, statement )
if not statement then
error( 'statement is not specified or nil' )
end
if not statement.type or statement.type ~= 'statement' then
throwError( 'unknown-claim-type' )
end
local functionToCall = getUserFunction( options, 'claim', context.formatStatementDefault )
return functionToCall( context, options, statement )
end
---@param statement table
---@return table
function getSourcingCircumstances( statement )
if not statement then
error( 'statement is not specified' )
end
local circumstances = {}
if statement.qualifiers and statement.qualifiers.P1480 then
for _, qualifier in pairs( statement.qualifiers.P1480 ) do
if qualifier
and qualifier.datavalue
and qualifier.datavalue.type == 'wikibase-entityid'
and qualifier.datavalue.value
and qualifier.datavalue.value[ 'entity-type'] == 'item'
then
table.insert( circumstances, qualifier.datavalue.value.id )
end
end
end
return circumstances
end
---Функция для оформления одного утверждения (statement)
---@param context table Context.
---@param options table Parameters.
---@param statement table
---@return string Formatted wikitext.
function formatStatementDefault( context, options, statement )
if not context then error( 'context is not specified' ) end
if not options then error( 'options is not specified' ) end
if not statement then error( 'statement is not specified' ) end
local circumstances = context.getSourcingCircumstances( statement )
options.qualifiers = statement.qualifiers
local result = context.formatSnak( options, statement.mainsnak, circumstances )
if options.qualifier and statement.qualifiers and statement.qualifiers[ options.qualifier ] then
local qualifierConfig = getPropertyParams( options.qualifier, nil, {} )
if options.i18n then
qualifierConfig.i18n = options.i18n
end
if qualifierConfig.datatype == 'time' then
qualifierConfig.nolinks = true
end
local qualifierValues = {}
for _, qualifierSnak in pairs( statement.qualifiers[ options.qualifier ] ) do
local snakValue = context.formatSnak( qualifierConfig, qualifierSnak )
if snakValue and snakValue ~= '' then
table.insert( qualifierValues, snakValue )
end
end
if result and result ~= '' and #qualifierValues then
if qualifierConfig.invisible then
result = result .. table.concat( qualifierValues, ', ' )
else
result = result .. ' (' .. table.concat( qualifierValues, ', ' ) .. ')'
end
end
end
if result and result ~= '' and options.references then
result = result .. context.formatRefs( options, statement )
end
return result
end
---Функция для оформления части утверждения (snak)
---Подробнее о snak см. d:Викиданные:Глоссарий
---@param context table Context.
---@param options table Parameters.
---@param snak table
---@param circumstances table
---@return string Formatted wikitext.
function formatSnak( context, options, snak, circumstances )
circumstances = circumstances or {}
local result
if snak.snaktype == 'somevalue' then
if options[ 'somevalue' ] and options[ 'somevalue' ] ~= '' then
result = options[ 'somevalue' ]
else
result = options.i18n[ 'somevalue' ]
end
elseif snak.snaktype == 'novalue' then
if options[ 'novalue' ] and options[ 'novalue' ] ~= '' then
result = options[ 'novalue' ]
else
result = options.i18n[ 'novalue' ]
end
elseif snak.snaktype == 'value' then
result = formatDatavalue( context, options, snak.datavalue, snak.datatype )
for _, item in pairs( circumstances ) do
if options.i18n[ item ] then
result = options.i18n[ item ] .. result
end
end
else
throwError( 'unknown-snak-type' )
end
if not result or result == '' then
return nil
end
if options.plain then
return result
end
return context.wrapSnak( result, snak.hash )
end
---Функция для оформления объектов-значений с географическими координатами
---@param value string Raw value.
---@param options table Parameters.
---@return string Formatted string.
local function formatGlobeCoordinate( value, options )
-- проверка на требование в параметрах вызова на возврат сырого значения
if options[ 'subvalue' ] == 'latitude' then -- широты
return value[ 'latitude' ]
elseif options[ 'subvalue' ] == 'longitude' then -- долготы
return value[ 'longitude' ]
elseif options[ 'nocoord' ] and options[ 'nocoord' ] ~= '' then
-- если передан параметр nocoord, то не выводить координаты
-- обычно это делается при использовании нескольких карточек на странице
return ''
else
-- в противном случае формируются параметры для вызова шаблона {{coord}}
-- нужно дописать в документации шаблона, что он отсюда вызывается, и что
-- любое изменние его парамеров должно быть согласовано с кодом тут
local coordModule = require( 'Module:Coordinates' )
local globe = options.globe or ''
if globe == '' and value[ 'globe' ] then
local globes = require( 'Module:Wikidata/Globes' )
globe = globes[ value[ 'globe' ] ] or ''
end
local display = 'inline'
if options.display and options.display ~= '' then
display = options.display
elseif ( options.property:upper() == 'P625' ) then
display = 'title'
end
local format = options.format or ''
if format == '' then
format = 'dms'
if value[ 'precision' ] then
local precision = value[ 'precision' ] * 60
if precision >= 60 then
format = 'd'
elseif precision >= 1 then
format = 'dm'
end
end
end
g_frame.args = {
tostring( value[ 'latitude' ] ),
tostring( value[ 'longitude' ] ),
globe = globe,
type = options.type and options.type or '',
scale = options.scale and options.scale or '',
display = display,
format = format,
}
return coordModule.coord(g_frame)
end
end
---Функция для оформления объектов-значений с файлами с Викисклада
---@param value string Raw value.
---@param options table Parameters.
---@return string Formatted string.
local function formatCommonsMedia( value, options )
local image = value
local caption = ''
if options[ 'caption' ] and options[ 'caption' ] ~= '' then
caption = options[ 'caption' ]
end
if caption ~= '' then
caption = wrapQualifier( caption, 'P2096', { class = 'media-caption', style = 'display:block' } )
end
if not string.find( value, '[%[%]%{%}]' ) and not string.find( value, 'UNIQ%-%-imagemap' ) then
-- если в value не содержится викикод или imagemap, то викифицируем имя файла
-- ищем слово imagemap в строке, потому что вставляется плейсхолдер: [[phab:T28213]]
image = '[[File:' .. value .. '|frameless'
if options[ 'border' ] and options[ 'border' ] ~= '' then
image = image .. '|border'
end
local size = options[ 'size' ]
if size and size ~= '' then
-- TODO: check localized pixel names too
if not string.match( size, 'px$' ) then
size = size .. 'px'
end
else
size = fileDefaultSize
end
image = image .. '|' .. size
if options[ 'alt' ] and options[ 'alt' ] ~= '' then
image = image .. '|alt=' .. options[ 'alt' ]
end
if caption ~= '' then
image = image .. '|' .. caption
end
image = image .. ']]'
if caption ~= '' then
image = image .. '<br>' .. caption
end
else
image = image .. caption .. getCategoryByCode( 'media-contains-markup' )
end
return image
end
---Function for render math formulas
---@param value string Value.
---@param options table Parameters.
---@return string Formatted string.
local function formatMath( value, options )
return options.frame:extensionTag{ name = 'math', content = value }
end
---Функция для оформления внешних идентификаторов
---@param value string
---@param options table
---@return string
local function formatExternalId( value, options )
local formatter = options.formatter
local propertyId = options.property:upper()
if not formatter or formatter == '' then
local isGoodFormat = false
local wbStatus, formatRegexStatements = pcall( mw.wikibase.getBestStatements, propertyId, 'P1793' )
if wbStatus and formatRegexStatements then
for _, statement in pairs( formatRegexStatements ) do
if statement.mainsnak.snaktype == 'value' then
local pattern = mw.ustring.gsub( statement.mainsnak.datavalue.value, '\\', '%' )
pattern = mw.ustring.gsub( pattern, '{%d+,?%d*}', '+' )
if ( string.find( pattern, '|' ) or string.find( pattern, '%)%?' )
or mw.ustring.match( value, '^' .. pattern .. '$' ) ~= nil ) then
isGoodFormat = true
break
end
end
end
end
if isGoodFormat then
local formatterStatements
wbStatus, formatterStatements = pcall( mw.wikibase.getBestStatements, propertyId, 'P1630' )
if wbStatus and formatterStatements then
for _, statement in pairs( formatterStatements ) do
if statement.mainsnak.snaktype == 'value' then
formatter = statement.mainsnak.datavalue.value
break
end
end
end
end
end
if formatter and formatter ~= '' then
local encodedValue = mw.ustring.gsub( value, '%%', '%%%%' ) -- ломается, если подставить внутрь другого mw.ustring.gsub
local link = mw.ustring.gsub(
mw.ustring.gsub( formatter, '$1', encodedValue ), '.',
{ [ ' ' ] = '%20', [ '+' ] = '%2b', [ '[' ] = '%5B', [ ']' ] = '%5D' } )
local title = options.title
if not title or title == '' then
title = '$1'
end
title = mw.ustring.gsub(
mw.ustring.gsub( title, '$1', encodedValue ), '.',
{ [ '[' ] = '(', [ ']' ] = ')' } )
return '[' .. link .. ' ' .. title .. ']'
end
return value
end
---Функция для оформления числовых значений
---@param value table Объект-значение
---@param options table Таблица параметров
---@return string Оформленный текст
local function formatQuantity( value, options )
-- диапазон значений
local amount = string.gsub( value.amount, '^%+', '' )
local lang = mw.language.getContentLanguage()
local langCode = lang:getCode()
local function formatNum( number, sigfig )
local multiplier = ''
if options.countByThousands then
local powers = options.i18n.thousandPowers
local pos = 1
while math.abs( number ) >= 1000 and pos < #powers do
number = number / 1000
pos = pos + 1
end
multiplier = powers[ pos ]
if math.abs( number ) >= 100 then
sigfig = sigfig or 0
elseif math.abs( number ) >= 10 then
sigfig = sigfig or 1
else
sigfig = sigfig or 2
end
else
sigfig = sigfig or 12 -- округление до 12 знаков после запятой, на 13-м возникает ошибка в точности
end
local iMultiplier = 10^sigfig
number = math.floor( number * iMultiplier + 0.5 ) / iMultiplier
return string.gsub( lang:formatNum( number ), '^-', '−' ) .. multiplier
end
local out = formatNum( tonumber( amount ) )
if value.upperBound then
local diff = tonumber( value.upperBound ) - tonumber( amount )
if diff > 0 then -- временная провека, пока у большинства значений не будет убрано ±0
-- Пробуем понять до какого знака округлять
local integer, dot, decimals, _ = value.upperBound:match( '^+?-?(%d*)(%.?)(%d*)(.*)' )
local precision
if dot == '' then
precision = -integer:match( '0*$' ):len()
else
precision = #decimals
end
local bound = formatNum( diff, precision )
if string.match( bound, 'E%-(%d+)' ) then -- если в экспоненциальном формате
local digits = tonumber( string.match( bound, 'E%-(%d+)' ) ) - 2
bound = formatNum( diff * 10 ^ digits, precision )
bound = string.sub( bound, 0, 2 ) .. string.rep( '0', digits ) .. string.sub( bound, -string.len( bound ) + 2 )
end
out = out .. ' ± ' .. bound
end
end
if options.unit and options.unit ~= '' then
if options.unit ~= '-' then
out = out .. ' ' .. options.unit
end
elseif value.unit and string.match( value.unit, 'http://www.wikidata.org/entity/' ) then
local unitEntityId = string.gsub( value.unit, 'http://www.wikidata.org/entity/', '' )
if unitEntityId ~= 'undefined' then
local wbStatus, unitEntity = pcall( mw.wikibase.getEntity, unitEntityId )
if wbStatus == true and unitEntity then
if unitEntity.claims.P2370 and
unitEntity.claims.P2370[ 1 ].mainsnak.snaktype == 'value' and
not value.upperBound and
options.siConversion == true
then
local conversionToSiUnit = string.gsub( unitEntity.claims.P2370[ 1 ].mainsnak.datavalue.value.amount, '^%+', '' )
if math.floor( math.log10( conversionToSiUnit ) ) ~= math.log10( conversionToSiUnit ) then
-- Если не степени десятки (переводить сантиметры в метры не надо!)
local outValue = tonumber( amount ) * conversionToSiUnit
if outValue > 0 then
-- Пробуем понять до какого знака округлять
local integer, dot, decimals, _ = amount:match( '^(%d*)(%.?)(%d*)(.*)' )
local precision
if dot == '' then
precision = -integer:match( '0*$' ):len()
else
precision = #decimals
end
local adjust = math.log10( math.abs( conversionToSiUnit ) ) + math.log10( 2 )
local minPrecision = 1 - math.floor( math.log10( outValue ) + 2e-14 )
out = formatNum( outValue, math.max( math.floor( precision + adjust ), minPrecision ) )
else
out = formatNum( outValue, 0 )
end
unitEntityId = string.gsub( unitEntity.claims.P2370[ 1 ].mainsnak.datavalue.value.unit, 'http://www.wikidata.org/entity/', '' )
wbStatus, unitEntity = pcall( mw.wikibase.getEntity, unitEntityId )
end
end
local label = getLabelWithLang( context, options, unitEntity.id, nil, { "P5061", "P558", "P558" }, {
'P5061[language:' .. langCode .. ']',
'P558[P282:' .. writingSystemElementId .. ', P407:' .. langElementId .. ']',
'P558[!P282][!P407]'
} )
out = out .. ' ' .. label
end
end
end
return out
end
---Функция для оформления URL
---@param context table
---@param options table
---@param value string
local function formatUrlValue( context, options, value )
if not options.length or options.length == '' then
options.length = 25
end
local moduleUrl = require( 'Module:URL' )
return moduleUrl.formatUrlSingle( context, options, value )
end
local DATATYPE_CACHE = {}
---Get property datatype by ID.
---@param propertyId string Property ID, e.g. 'P123'.
---@return string Property datatype, e.g. 'commonsMedia', 'time' or 'url'.
local function getPropertyDatatype( propertyId )
if not propertyId or not string.match( propertyId, '^P%d+$' ) then
return nil
end
local cached = DATATYPE_CACHE[ propertyId ]
if cached ~= nil then
return cached
end
local wbStatus, propertyEntity = pcall( mw.wikibase.getEntity, propertyId )
if wbStatus ~= true or not propertyEntity then
return nil
end
mw.log("Loaded datatype " .. propertyEntity.datatype .. " of " .. propertyId .. ' from wikidata, consider passing datatype argument to formatProperty call or to Wikidata/config' )
DATATYPE_CACHE[ propertyId ] = propertyEntity.datatype
return propertyEntity.datatype
end
---@param datavalue table
---@return function
local function getPlainValueFunction( datavalue, _ )
if datavalue.type == 'wikibase-entityid' then
return function( _, _, value )
return getEntityIdFromValue( value )
end
elseif datavalue.type == 'string' then
return function( _, _, value )
return value
end
elseif datavalue.type == 'monolingualtext' then
return function( _, _, value )
return value.text
end
elseif datavalue.type == 'globecoordinate' then
return function( _, _, value )
return value.latitude .. ',' .. value.longitude
end
elseif datavalue.type == 'quantity' then
return function( _, _, value )
return value.amount
end
elseif datavalue.type == 'time' then
return function( _, _, value )
return value.time
end
end
throwError( 'unknown-datavalue-type' )
end
---@param datavalue table
---@param datatype string
---@return function
local function getDefaultValueFunction( datavalue, datatype )
-- вызов обработчиков по умолчанию для известных типов значений
if datavalue.type == 'wikibase-entityid' then
-- Entity ID
return function( context, options, value )
return formatEntityId( context, options, getEntityIdFromValue( value ) )
end
elseif datavalue.type == 'string' then
-- String
if datatype and datatype == 'commonsMedia' then
-- Media
return function( _, options, value )
return formatCommonsMedia( value, options )
end
elseif datatype and datatype == 'external-id' then
-- External ID
return function( _, options, value )
return formatExternalId( value, options )
end
elseif datatype and datatype == 'math' then
-- Math formula
return function( _, options, value )
return formatMath( value, options )
end
elseif datatype and datatype == 'url' then
-- URL
return formatUrlValue
end
return function( _, _, value )
return value
end
elseif datavalue.type == 'monolingualtext' then
-- моноязычный текст (строка с указанием языка)
return function( _, options, value )
if options.monolingualLangTemplate == 'lang' then
if value.language == CONTENT_LANGUAGE_CODE then
return value.text
end
return options.frame:expandTemplate{ title = 'lang-' .. value.language, args = { value.text } }
elseif options.monolingualLangTemplate == 'ref' then
return '<span class="lang" lang="' .. value.language .. '">' .. value.text .. '</span>' .. options.frame:expandTemplate{ title = 'ref-' .. value.language }
else
return '<span class="lang" lang="' .. value.language .. '">' .. value.text .. '</span>'
end
end
elseif datavalue.type == 'globecoordinate' then
-- географические координаты
return function( _, options, value )
return formatGlobeCoordinate( value, options )
end
elseif datavalue.type == 'quantity' then
return function( _, options, value )
return formatQuantity( value, options )
end
elseif datavalue.type == 'time' then
return function( context, options, value )
local moduleDate = require( 'Module:Wikidata/date' )
return moduleDate.formatDate( context, options, value )
end
end
-- во всех стальных случаях возвращаем ошибку
throwError( 'unknown-datavalue-type' )
end
---Функция для оформления значений (value)
---Подробнее о значениях см. d:Wikidata:Glossary/ru
---@param context table
---@param options table
---@param datavalue table
---@param datatype string
---@return string Оформленный текст
function formatDatavalue( context, options, datavalue, datatype )
if not context then error( 'context not specified' ); end
if not options then error( 'options not specified' ); end
if not datavalue then error( 'datavalue not specified' ); end
if not datavalue.value then error( 'datavalue.value is missing' ); end
-- проверка на указание специализированных обработчиков в параметрах,
-- переданных при вызове
if options.plain then
context.formatValueDefault = getPlainValueFunction( datavalue, datatype )
else
context.formatValueDefault = getDefaultValueFunction( datavalue, datatype )
end
local functionToCall = getUserFunction( options, 'value', context.formatValueDefault )
return functionToCall( context, options, datavalue.value )
end
local DEFAULT_BOUNDARIES = { os.time() * 1000, os.time() * 1000}
---Функция для оформления идентификатора сущности
---@param context table
---@param options table
---@param entityId string
---@return string Оформленный текст
function formatEntityId( context, options, entityId )
-- получение локализованного названия
local boundaries
if options.qualifiers then
boundaries = p.getTimeBoundariesFromQualifiers( context.frame, context, { qualifiers = options.qualifiers } )
end
if not boundaries then
boundaries = DEFAULT_BOUNDARIES
end
local label, labelLanguageCode = getLabelWithLang( context, options, entityId, boundaries )
-- определение соответствующей показываемому элементу категории
local category = context.extractCategory( options, { id = entityId } )
-- получение ссылки по идентификатору
local link = mw.wikibase.sitelink( entityId )
if link then
-- ссылка на категорию, а не добавление страницы в неё
if mw.ustring.match( link, '^' .. mw.site.namespaces[ 14 ].name .. ':' ) then
link = ':' .. link
end
if label and not options.rawArticle then
if labelLanguageCode ~= CONTENT_LANGUAGE_CODE then
label = '<span lang="' .. label .. '">' .. label .. '</span>'
end
local a = '[[' .. link .. '|' .. label .. ']]'
if CONTENT_LANGUAGE_CODE ~= labelLanguageCode and 'mul' ~= labelLanguageCode then
a = a .. getCategoryByCode( 'links-to-entities-with-missing-local-language-label' )
end
return a .. category
else
return '[[' .. link .. ']]' .. category
end
end
if label then -- TODO: возможно, лучше просто mw.wikibase.getLabel(entityId)
-- красная ссылка
-- TODO: разобраться, почему не всегда есть options.frame
local moduleRedLink = require( 'Module:Wikidata/redLink' )
local title = mw.title.new( label )
if title and not title.exists and options.frame then
local rawLabel = mw.wikibase.getLabel(entityId) or label -- без |text= и boundaries; or label - костыль
local redLink = moduleRedLink.formatRedLinkWithInfobox(rawLabel, label, entityId)
if CONTENT_LANGUAGE_CODE ~= labelLanguageCode and 'mul' ~= labelLanguageCode then
redLink = '<span lang="' .. labelLanguageCode .. '">' .. redLink .. '</span>' ..
getCategoryByCode( 'links-to-entities-with-missing-local-language-label' )
end
return redLink .. category
end
-- TODO: перенести до проверки на существование статьи
local addWdLink = false
if ( not options.format or options.format ~= 'text' )
and entityId ~= 'Q6581072' and entityId ~= 'Q6581097' -- TODO: переписать на format=text
then
addWdLink = true
end
-- одноимённая статья уже существует - выводится текст и ссылка на ВД
return moduleRedLink.formatText(label, entityId, addWdLink) .. category
end
-- сообщение об отсутвии локализованного названия
-- not good, but better than nothing
return '[[:d:' .. entityId .. '|' .. entityId .. ']]<span style="border-bottom: 1px dotted; cursor: help; white-space: nowrap" title="В Викиданных нет русской подписи к элементу. Вы можете помочь, указав русский вариант подписи.">?</span>' .. getCategoryByCode( 'links-to-entities-with-missing-label' ) .. category
end
---Функция для оформления утверждений (statement)
---Подробнее о утверждениях см. d:Wikidata:Glossary/ru
---@deprecated Use p.formatProperty() instead
---@param frame table
---@return string Строка оформленного текста, предназначенная для отображения в статье
function p.formatStatements( frame )
return p.formatProperty( frame )
end
---Получение параметров, которые обычно используются для вывода свойства.
---@param propertyId string
---@param datatype string
---@param params table
function getPropertyParams( propertyId, datatype, params )
local config = getConfig()
-- Различные уровни настройки параметров, по убыванию приоритета
local propertyParams = {}
-- 1. Параметры, указанные явно при вызове
if params then
for key, value in pairs( params ) do
if value ~= '' then
propertyParams[ key ] = value
end
end
end
if toBoolean( propertyParams.plain, false ) then
propertyParams.separator = propertyParams.separator or ', '
propertyParams.conjunction = propertyParams.conjunction or ', '
else
-- 2. Настройки конкретного параметра
if config.properties and config.properties[ propertyId ] then
for key, value in pairs( config.properties[ propertyId ] ) do
if propertyParams[ key ] == nil then
propertyParams[ key ] = value
end
end
end
-- 3. Указанный пресет настроек
if propertyParams.preset and config.presets and
config.presets[ propertyParams.preset ]
then
for key, value in pairs( config.presets[ propertyParams.preset ] ) do
if propertyParams[ key ] == nil then
propertyParams[ key ] = value
end
end
end
datatype = datatype or params.datatype or propertyParams.datatype or getPropertyDatatype( propertyId )
if propertyParams.datatype == nil then
propertyParams.datatype = datatype
end
-- 4. Настройки для типа данных
if datatype and config.datatypes and config.datatypes[ datatype ] then
for key, value in pairs( config.datatypes[ datatype ] ) do
if propertyParams[ key ] == nil then
propertyParams[ key ] = value
end
end
end
-- 5. Общие настройки для всех свойств
if config.global then
for key, value in pairs( config.global ) do
if propertyParams[ key ] == nil then
propertyParams[ key ] = value
end
end
end
end
return propertyParams
end
---Функция для оформления утверждений (statement)
---Подробнее о утверждениях см. d:Wikidata:Glossary/ru
---@param frame table
---@return string Строка оформленного текста, предназначенная для отображения в статье
function p.formatProperty( frame )
local args = copyTo( frame.args, {} )
-- проверка на отсутствие обязательного параметра property
if not args.property then
throwError( 'property-param-not-provided' )
end
local override
local propertyId = mw.language.getContentLanguage():ucfirst( string.gsub( args.property, '([^Pp0-9].*)$', function(w)
if string.sub( w, 1, 1 ) == '~' then
override = w
end
return ''
end ) )
if override then
args[ override:match( '[,~]([^=]*)=' ) ] = override:match( '=(.*)' )
args.property = propertyId
end
-- проброс всех параметров из шаблона {wikidata} и параметра from откуда угодно
local p_frame = frame
while p_frame do
if p_frame:getTitle() == mw.site.namespaces[ 10 ].name .. ':Wikidata' then
copyTo( p_frame.args, args, true )
end
if p_frame.args and p_frame.args.from and p_frame.args.from ~= '' then
args.entityId = p_frame.args.from
else
args.entityId = mw.wikibase.getEntityIdForCurrentPage()
end
p_frame = p_frame:getParent()
end
args = getPropertyParams( propertyId, nil, args )
local datatype = args.datatype
-- перевод итоговых значений флагов в true/false и добавление значений
-- по умолчанию только в том случае, если они нигде не были указаны ранее
args.plain = toBoolean( args.plain, false )
args.nocat = not args.plain and toBoolean( args.nocat, false )
args.references = not args.plain and toBoolean( args.references, true )
-- если значение передано в параметрах вызова то выводим только его
if args.value and args.value ~= '' then
-- специальное значение для скрытия Викиданных
if args.value == '-' then
return ''
end
local value = args.value
-- опция, запрещающая оформление значения, поэтому никак не трогаем
if args.plain then
return value
end
local context = initContext( args )
-- обработчики по типу значения
local wrapperExtraArgs = {}
if args[ 'value-module' ] and args[ 'value-function' ] and not string.find( value, '[%[%]%{%}]' ) then
local func = getUserFunction( args, 'value' )
value = func( context, args, value )
elseif datatype == 'commonsMedia' then
value = formatCommonsMedia( value, args )
elseif datatype == 'external-id' and not string.find( value, '[%[%]%{%}]' ) then
wrapperExtraArgs[ 'data-wikidata-external-id' ] = mw.text.killMarkers( value )
value = formatExternalId( value, args )
--elseif datatype == 'math' then
-- args.frame = frame -- костыль: в formatMath нужно frame:extensionTag
-- value = formatMath( value, args )
elseif datatype == 'url' then
value = formatUrlValue( context, args, value )
end
-- оборачиваем в тег для JS-функций
if string.match( propertyId, '^P%d+$' ) then
value = mw.text.trim( value )
-- временная штрафная категория для исправления табличных вставок
local allowTables = getPropertyParams( propertyId, nil, {} ).allowTables
if not allowTables
and string.match( value, '<t[dhr][ >]' )
-- and not string.match( value, '<table[ >]' )
-- and not string.match( value, '^%{%|' )
then
value = value .. getCategoryByCode( 'value-contains-table', propertyId )
else
value = wrapStatement( value, propertyId, nil, wrapperExtraArgs )
end
end
return value
end
-- ability to disable loading Wikidata
if args.entityId == '-' then
return ''
end
g_frame = frame
-- после проверки всех аргументов -- вызов функции оформления для свойства (набора утверждений)
return formatProperty( args )
end
---Функция проверки на присутствие источника в списке нерекомендованных.
---@param snaks table
---@return boolean
local function isReferenceDeprecated( snaks )
if not snaks then
return false
end
if snaks.P248
and snaks.P248[ 1 ]
and snaks.P248[ 1 ].datavalue
and snaks.P248[ 1 ].datavalue.value.id
then
local entityId = snaks.P248[ 1 ].datavalue.value.id
if getConfig( 'deprecatedSources', entityId ) then
return true
end
elseif snaks.P1433
and snaks.P1433[ 1 ]
and snaks.P1433[ 1 ].datavalue
and snaks.P1433[ 1 ].datavalue.value.id
then
local entityId = snaks.P1433[ 1 ].datavalue.value.id
if getConfig( 'deprecatedSources', entityId ) then
return true
end
end
return false
end
---Функция оформления ссылок на источники (reference)
---Подробнее о ссылках на источники см. d:Wikidata:Glossary/ru
---
---Экспортируется в качестве зарезервированной точки для вызова из функций-расширения вида claim-module/claim-function через context
---Вызов из других модулей напрямую осуществляться не должен (используйте frame:expandTemplate вместе с одним из специлизированных шаблонов вывода значения свойства).
---@param context table
---@param options table
---@param statement table
---@return string Оформленные примечания для отображения в статье
function formatRefs( context, options, statement )
if not context then error( 'context not specified' ); end
if not options then error( 'options not specified' ); end
if not options.entityId then error( 'options.entityId missing' ); end
if not statement then error( 'statement not specified' ); end
if not outputReferences then
return ''
end
---@type string[]
local references = {}
if statement.references then
local hasNotDeprecated = false
local displayCount = 0
for _, reference in pairs( statement.references ) do
if not isReferenceDeprecated( reference.snaks ) then
hasNotDeprecated = true
end
end
for _, reference in pairs( statement.references ) do
local display = true
if hasNotDeprecated then
if isReferenceDeprecated( reference.snaks ) then
display = false
end
end
if displayCount >= 2 then
if options.entityId and options.property then
local propertyId = mw.ustring.match( options.property, '^[Pp][0-9]+' ) -- TODO: обрабатывать не тут, а раньше
local moreReferences = '<sup>[[d:' .. options.entityId .. '#' .. string.upper( propertyId ) .. '|[…]]]</sup>'
table.insert( references, moreReferences )
end
break
end
if display == true then
---@type string
local refText = moduleSources.renderReference( g_frame, options.entityId, reference )
if refText and refText ~= '' then
table.insert( references, refText )
displayCount = displayCount + 1
end
end
end
end
return table.concat( references )
end
return p
4558f762f30c6ebfb9f5333dbd7ebda83c6873f2
Модуль:Wikidata/media
828
54
105
2024-10-26T15:20:21Z
wikipedia:ru>Stjn
0
[[ВП:×|отмена]]: сломало отображение в множестве статей
Scribunto
text/plain
local p = {}
-- Константы
local contentLanguageCode = mw.getContentLanguage():getCode();
function p.formatCommonsCategory( context, options, value )
local link = 'commons:Category:' .. value
local title = value .. ' на Викискладе'
if ( options['text'] and options['text'] ~= '' ) then
title = options['text']
end
commons = '[[' .. link .. '|' .. title .. ']]'
--Commons icon
if ( not options['icon'] or options['icon'] ~= '-' ) then
local icon_size = '15px'
if ( options['icon_size'] and options['icon_size'] ~= '' ) then
icon_size = options['icon_size']
end
commons = '[[File:Commons-logo.svg|' .. icon_size .. '|link=' .. link .. '|alt=Логотип Викисклада]] ' .. commons
end
--Text before and after link
if ( options['text_before'] and options['text_before'] ~= '' ) then
if ( options['text_before'] ~= '-' ) then
commons = options['text_before'] .. ' ' .. commons
end
end
if ( options['text_after'] and options['text_after'] ~= '' ) then
if ( options['text_after'] ~= '-' ) then
commons = commons .. ' ' .. options['text_after']
end
end
return commons
end
--[[
Временный хак, нужно добавить config, getConfig и getCategoryByCode
в options, чтобы они были доступны в любом месте кода.
]]
local config;
local function getCategoryByCode( code, sortkey )
if config == nil then
config = require( 'Module:Wikidata/config' );
end;
local value = config[ 'categories' ][ code ];
if not value or value == '' then
return '';
end
return '[[Category:' .. value .. ']]';
end
local function getCaption( context, options )
local caption = ''
if options.qualifiers and options.qualifiers.P2096 then
for i, qualifier in pairs( options.qualifiers.P2096 ) do
if ( qualifier
and qualifier.datavalue
and qualifier.datavalue.type == 'monolingualtext'
and qualifier.datavalue.value
and qualifier.datavalue.value.language == contentLanguageCode ) then
caption = qualifier.datavalue.value.text
break
end
end
end
if options['appendTimestamp'] and options.qualifiers and options.qualifiers.P585 and options.qualifiers.P585[1] then
local moment = context.formatValueDefault( context, options, options.qualifiers.P585[1].datavalue )
if not caption or caption == '' then
caption = moment
else
caption = caption .. ', ' .. moment
end
end
local localValue = '';
if options[ 'value' ] and options[ 'value' ] ~= '' then
localValue = options[ 'value' ];
end
local localCaption = '';
if options[ 'caption' ] and options[ 'caption' ] ~= '' then
localCaption = options[ 'caption' ];
end
if localValue ~= '' then
caption = localCaption;
end
local formattedCaption = ''
if caption ~= '' then
formattedCaption = context.wrapQualifier( caption, 'P2096', { class = 'media-caption', style = 'display:block' } );
end
if localValue == '' and localCaption ~= '' then
formattedCaption = formattedCaption .. getCategoryByCode( 'media-contains-local-caption' )
if options.frame:preprocess('{{REVISIONID}}') == '' then
formattedCaption = formattedCaption .. '<span class="error" style="font-size:94%;">Локальная подпись не используется, потому что изображение берётся из Викиданных, см. [[Википедия:Шаблоны-карточки#Описание изображения в Викиданных|здесь]]</span>'
end
end
return caption, formattedCaption
end
function p.formatCommonsMediaValue( context, options, value )
local image = value;
local caption, formattedCaption = getCaption( context, options )
if not string.find( value, '[%[%]%{%}]' ) and not string.find( value, 'UNIQ%-%-imagemap' ) then
-- если в value не содержится викикод или imagemap, то викифицируем имя файла
-- ищем слово imagemap в строке, потому что вставляется плейсхолдер: [[PHAB:T28213]]
image = '[[File:' .. value .. '|frameless';
if options[ 'border' ] and options[ 'border' ] ~= '' then
image = image .. '|border';
end
local size = options[ 'size' ];
if size and size ~= '' then
if not string.match( size, 'px$' )
and not string.match( size, 'пкс$' ) -- TODO: использовать перевод для языка вики
then
size = size .. 'px'
end
-- временно
if string.match( size, 'pxpx' ) then
image = '[[Категория:Википедия:Изображение с pxpx в размере]]' .. image
end
else
size = fileDefaultSize;
end
image = image .. '|' .. size;
if options[ 'alt' ] and options[ 'alt' ] ~= '' then
image = image .. '|alt=' .. options[ 'alt' ];
end
if caption ~= '' then
image = image .. '|' .. caption
end
image = image .. ']]';
if formattedCaption ~= '' then
image = image .. '<br>' .. formattedCaption;
end
else
image = image .. formattedCaption .. getCategoryByCode( 'media-contains-markup' );
end
if options.entity and options.fixdouble then
local page = mw.title.getCurrentTitle()
local txt = page:getContent()
if txt and txt:match(':' .. value) and mw.title.getCurrentTitle():inNamespace(0) then
if options.frame:preprocess('{{REVISIONID}}') == '' then
image = image .. '<span class="error">Это изображение встречается ниже по тексту статьи; пожалуйста, уберите одну из копий (не потеряв при этом подпись)</span>'
end
image = image .. getCategoryByCode( 'media-contains-local-double' )
end
end
return image
end
return p
ec384e72491465f4103cce95a8f9467df428a432
Модуль:String
828
30
57
2024-11-18T02:41:06Z
wikipedia:ru>Stjn
0
аналогично английскому разделу — mw.ustring.gsub тут не нужен
Scribunto
text/plain
--[[
This module is intended to provide access to basic string functions.
Most of the functions provided here can be invoked with named parameters,
unnamed parameters, or a mixture. If named parameters are used, Mediawiki will
automatically remove any leading or trailing whitespace from the parameter.
Depending on the intended use, it may be advantageous to either preserve or
remove such whitespace.
Global options
ignore_errors: If set to 'true' or 1, any error condition will result in
an empty string being returned rather than an error message.
error_category: If an error occurs, specifies the name of a category to
include with the error message. The default category is
[Category:Errors reported by Module String].
no_category: If set to 'true' or 1, no category will be added if an error
is generated.
Unit tests for this module are available at Module:String/tests.
]]
local str = {}
--[[
subcount
This function returns the count of substring in source string.
Usage:
{{#invoke:String|subcount|source_string|substring|plain_flag}}
OR
{{#invoke:String|subcount|s=source_string|pattern=substring|plain=plain_flag}}
Parameters
s: The string to search
pattern: The pattern or string to find within the string
plain: A flag indicating that the substring should be understood as plain
text. Defaults to true.
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string.
]]
function str.subcount( frame )
local new_args = str._getParameters( frame.args, {'s', 'pattern', 'plain'} );
local s = new_args['s'] or '';
local plain_flag = str._getBoolean( new_args['plain'] or true );
local pattern = new_args['pattern'] or '';
if s == '' or pattern == '' then
return 0;
end
if plain_flag then
pattern = str._escapePattern( pattern );
end
local _, count = mw.ustring.gsub(s, pattern, "")
return count;
end
--[[
len
This function returns the length of the target string.
Usage:
{{#invoke:String|len|target_string|}}
OR
{{#invoke:String|len|s=target_string}}
Parameters
s: The string whose length to report
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string.
]]
function str.len( frame )
local new_args = str._getParameters( frame.args, {'s'} );
local s = new_args['s'] or '';
return mw.ustring.len( s )
end
--[[
sub
This function returns a substring of the target string at specified indices.
Usage:
{{#invoke:String|sub|target_string|start_index|end_index}}
OR
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}}
Parameters
s: The string to return a subset of
i: The fist index of the substring to return, defaults to 1.
j: The last index of the string to return, defaults to the last character.
The first character of the string is assigned an index of 1. If either i or j
is a negative value, it is interpreted the same as selecting a character by
counting from the end of the string. Hence, a value of -1 is the same as
selecting the last character of the string.
If the requested indices are out of range for the given string, an error is
reported.
]]
function str.sub( frame )
local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } );
local s = new_args['s'] or '';
local i = tonumber( new_args['i'] ) or 1;
local j = tonumber( new_args['j'] ) or -1;
local len = mw.ustring.len( s );
-- Convert negatives for range checking
if i < 0 then
i = len + i + 1;
end
if j < 0 then
j = len + j + 1;
end
if i > len or j > len or i < 1 or j < 1 then
return str._error( 'Значение индекса подстроки выходит за допустимые границы' );
end
if j < i then
return str._error( 'Неверный порядок индексов подстроки' );
end
return mw.ustring.sub( s, i, j )
end
--[[
This function implements that features of {{str sub old}} and is kept in order
to maintain these older templates.
]]
function str.sublength( frame )
local i = tonumber( frame.args.i ) or 0
local len = tonumber( frame.args.len )
return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) )
end
--[[
match
This function returns a substring from the source string that matches a
specified pattern.
Usage:
{{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}}
OR
{{#invoke:String|pos|s=source_string|pattern=pattern_string|start=start_index
|match=match_number|plain=plain_flag|nomatch=nomatch_output}}
Parameters
s: The string to search
pattern: The pattern or string to find within the string
start: The index within the source string to start the search. The first
character of the string has index 1. Defaults to 1.
match: In some cases it may be possible to make multiple matches on a single
string. This specifies which match to return, where the first match is
match= 1. If a negative number is specified then a match is returned
counting from the last match. Hence match = -1 is the same as requesting
the last match. Defaults to 1.
plain: A flag indicating that the pattern should be understood as plain
text. Defaults to false.
nomatch: If no match is found, output the "nomatch" value rather than an error.
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from each string. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
If the match_number or start_index are out of range for the string being queried, then
this function generates an error. An error is also generated if no match is found.
If one adds the parameter ignore_errors=true, then the error will be suppressed and
an empty string will be returned on any failure.
For information on constructing Lua patterns, a form of [regular expression], see:
* http://www.lua.org/manual/5.1/manual.html#5.4.1
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns
]]
function str.match( frame )
local new_args = str._getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} );
local s = new_args['s'] or '';
local start = tonumber( new_args['start'] ) or 1;
local plain_flag = str._getBoolean( new_args['plain'] or false );
local pattern = new_args['pattern'] or '';
local match_index = math.floor( tonumber(new_args['match']) or 1 );
local nomatch = new_args['nomatch'];
if s == '' then
return str._error( 'Пустая строка поиска' );
end
if pattern == '' then
return str._error( 'Пустой шаблон поиска' );
end
if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then
return str._error( 'Индекс начала поиска выходит за допустимые границы' );
end
if match_index == 0 then
return str._error( 'Индекс совпадения выходит за допустимые границы' );
end
if plain_flag then
pattern = str._escapePattern( pattern );
end
local result
if match_index == 1 then
-- Find first match is simple case
result = mw.ustring.match( s, pattern, start )
else
if start > 1 then
s = mw.ustring.sub( s, start );
end
local iterator = mw.ustring.gmatch(s, pattern);
if match_index > 0 then
-- Forward search
for w in iterator do
match_index = match_index - 1;
if match_index == 0 then
result = w;
break;
end
end
else
-- Reverse search
local result_table = {};
local count = 1;
for w in iterator do
result_table[count] = w;
count = count + 1;
end
result = result_table[ count + match_index ];
end
end
if result == nil then
if nomatch == nil then
return str._error( 'Совпадение не найдено' );
else
return nomatch;
end
else
return result;
end
end
--[[
pos
This function returns a single character from the target string at position pos.
Usage:
{{#invoke:String|pos|target_string|index_value}}
OR
{{#invoke:String|pos|target=target_string|pos=index_value}}
Parameters
target: The string to search
pos: The index for the character to return
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
The first character has an index value of 1.
If one requests a negative value, this function will select a character by counting backwards
from the end of the string. In other words pos = -1 is the same as asking for the last character.
A requested value of zero, or a value greater than the length of the string returns an error.
]]
function str.pos( frame )
local new_args = str._getParameters( frame.args, {'target', 'pos'} );
local target_str = new_args['target'] or '';
local pos = tonumber( new_args['pos'] ) or 0;
if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then
return str._error( 'Значение индекса строки выходит за допустимые границы' );
end
return mw.ustring.sub( target_str, pos, pos );
end
--[[
str_find
This function duplicates the behavior of {{str_find}}, including all of its quirks.
This is provided in order to support existing templates, but is NOT RECOMMENDED for
new code and templates. New code is recommended to use the "find" function instead.
Returns the first index in "source" that is a match to "target". Indexing is 1-based,
and the function returns -1 if the "target" string is not present in "source".
Important Note: If the "target" string is empty / missing, this function returns a
value of "1", which is generally unexpected behavior, and must be accounted for
separatetly.
]]
function str.str_find( frame )
local new_args = str._getParameters( frame.args, {'source', 'target'} );
local source_str = new_args['source'] or '';
local target_str = new_args['target'] or '';
if target_str == '' then
return 1;
end
local start = mw.ustring.find( source_str, target_str, 1, true )
if start == nil then
start = -1
end
return start
end
--[[
find
This function allows one to search for a target string or pattern within another
string.
Usage:
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}}
OR
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}}
Parameters
source: The string to search
target: The string or pattern to find within source
start: The index within the source string to start the search, defaults to 1
plain: Boolean flag indicating that target should be understood as plain
text and not as a Lua style regular expression, defaults to true
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the parameter. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
This function returns the first index >= "start" where "target" can be found
within "source". Indices are 1-based. If "target" is not found, then this
function returns 0. If either "source" or "target" are missing / empty, this
function also returns 0.
This function should be safe for UTF-8 strings.
]]
function str.find( frame )
local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } );
local source_str = new_args['source'] or '';
local pattern = new_args['target'] or '';
local start_pos = tonumber(new_args['start']) or 1;
local plain = new_args['plain'] or true;
if source_str == '' or pattern == '' then
return 0;
end
plain = str._getBoolean( plain );
local start = mw.ustring.find( source_str, pattern, start_pos, plain )
if start == nil then
start = 0
end
return start
end
--[[
replace
This function allows one to replace a target string or pattern within another
string.
Usage:
{{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}}
OR
{{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string|
count=replacement_count|plain=plain_flag}}
Parameters
source: The string to search
pattern: The string or pattern to find within source
replace: The replacement text
count: The number of occurences to replace, defaults to all.
plain: Boolean flag indicating that pattern should be understood as plain
text and not as a Lua style regular expression, defaults to true
]]
function str.replace( frame )
local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } );
local source_str = new_args['source'] or '';
local pattern = new_args['pattern'] or '';
local replace = new_args['replace'] or '';
local count = tonumber( new_args['count'] );
local plain = new_args['plain'] or true;
if source_str == '' or pattern == '' then
return source_str;
end
plain = str._getBoolean( plain );
if plain then
pattern = str._escapePattern( pattern );
replace = string.gsub( replace, "%%", "%%%%" ) --Only need to escape replacement sequences.
end
local result;
if count ~= nil then
result = mw.ustring.gsub( source_str, pattern, replace, count );
else
result = mw.ustring.gsub( source_str, pattern, replace );
end
return result;
end
--[[
This function adds support for escaping parts of the patterns when using [plain=false].
]]
function str.escape( frame )
local new_args = str._getParameters( frame.args, {'pattern' } );
local pattern = new_args['pattern'] or '';
local result = '';
result = str._escapePattern( pattern );
return result;
end
--[[
Internal compare string function
]]
function str._strcmp(a , b)
local s1c = mw.ustring.gcodepoint( a );
local s2c = mw.ustring.gcodepoint( b );
while true do
local c1 = s1c();
local c2 = s2c();
if c1 == nil then
if c2 == nil then
return 0
else
return -1
end
else
if c2 ~= nil then
if c1 ~= c2 then
return c1 < c2 and -1 or 1
end
else
return 1
end
end
end
return 0
end
--[[
compare
This function compare two UTF-8 strings
Usage:
{{#invoke:String|compare|str1|str2}}
Returns:
0 - if strings are equal
1 - if st1 > str2
-1 - if str1 < str2
]]
function str.compare(frame)
local str1 = frame.args[1] or '';
local str2 = frame.args[2] or '';
return str._strcmp(str1 , str2)
end
--[[
simple function to pipe string.rep to templates.
]]
function str.rep( frame )
local repetitions = tonumber( frame.args[2] )
if not repetitions then
return str._error( 'функция rep ожидает число во втором параметре, а получено "' .. ( frame.args[2] or '' ) .. '"' )
end
return string.rep( frame.args[1] or '', repetitions )
end
--[[
Helper function that populates the argument list given that user may need to use a mix of
named and unnamed parameters. This is relevant because named parameters are not
identical to unnamed parameters due to string trimming, and when dealing with strings
we sometimes want to either preserve or remove that whitespace depending on the application.
]]
function str._getParameters( frame_args, arg_list )
local new_args = {};
local index = 1;
local value;
for i,arg in ipairs( arg_list ) do
value = frame_args[arg]
if value == nil then
value = frame_args[index];
index = index + 1;
end
new_args[arg] = value;
end
return new_args;
end
--[[
Helper function to handle error messages.
]]
function str._error( error_str )
local frame = mw.getCurrentFrame();
local error_category = frame.args.error_category or 'Страницы с ошибками модуля String';
local ignore_errors = frame.args.ignore_errors or false;
local no_category = frame.args.no_category or false;
if str._getBoolean(ignore_errors) then
return '';
end
local error_str = '<strong class="error">Ошибка модуля String: ' .. error_str .. '</strong>';
if error_category ~= '' and not str._getBoolean( no_category ) then
error_str = '[[Категория:' .. error_category .. ']]' .. error_str;
end
return error_str;
end
--[[
Helper Function to interpret boolean strings
]]
function str._getBoolean( boolean_str )
local boolean_value;
if type( boolean_str ) == 'string' then
boolean_str = boolean_str:lower();
if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0'
or boolean_str == '' then
boolean_value = false;
else
boolean_value = true;
end
elseif type( boolean_str ) == 'boolean' then
boolean_value = boolean_str;
else
error( 'Логическое значение не найдено' );
end
return boolean_value
end
--[[
Helper function that escapes all pattern characters so that they will be treated
as plain text.
]]
function str._escapePattern( pattern_str )
return ( string.gsub( pattern_str, "[%(%)%.%%%+%-%*%?%[%^%$%]]", "%%%0" ) )
end
return str
2c7347f1dafbbc0efc196c148a1f81e7b82420dc
58
57
2025-01-25T21:00:16Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--[[
This module is intended to provide access to basic string functions.
Most of the functions provided here can be invoked with named parameters,
unnamed parameters, or a mixture. If named parameters are used, Mediawiki will
automatically remove any leading or trailing whitespace from the parameter.
Depending on the intended use, it may be advantageous to either preserve or
remove such whitespace.
Global options
ignore_errors: If set to 'true' or 1, any error condition will result in
an empty string being returned rather than an error message.
error_category: If an error occurs, specifies the name of a category to
include with the error message. The default category is
[Category:Errors reported by Module String].
no_category: If set to 'true' or 1, no category will be added if an error
is generated.
Unit tests for this module are available at Module:String/tests.
]]
local str = {}
--[[
subcount
This function returns the count of substring in source string.
Usage:
{{#invoke:String|subcount|source_string|substring|plain_flag}}
OR
{{#invoke:String|subcount|s=source_string|pattern=substring|plain=plain_flag}}
Parameters
s: The string to search
pattern: The pattern or string to find within the string
plain: A flag indicating that the substring should be understood as plain
text. Defaults to true.
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string.
]]
function str.subcount( frame )
local new_args = str._getParameters( frame.args, {'s', 'pattern', 'plain'} );
local s = new_args['s'] or '';
local plain_flag = str._getBoolean( new_args['plain'] or true );
local pattern = new_args['pattern'] or '';
if s == '' or pattern == '' then
return 0;
end
if plain_flag then
pattern = str._escapePattern( pattern );
end
local _, count = mw.ustring.gsub(s, pattern, "")
return count;
end
--[[
len
This function returns the length of the target string.
Usage:
{{#invoke:String|len|target_string|}}
OR
{{#invoke:String|len|s=target_string}}
Parameters
s: The string whose length to report
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string.
]]
function str.len( frame )
local new_args = str._getParameters( frame.args, {'s'} );
local s = new_args['s'] or '';
return mw.ustring.len( s )
end
--[[
sub
This function returns a substring of the target string at specified indices.
Usage:
{{#invoke:String|sub|target_string|start_index|end_index}}
OR
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}}
Parameters
s: The string to return a subset of
i: The fist index of the substring to return, defaults to 1.
j: The last index of the string to return, defaults to the last character.
The first character of the string is assigned an index of 1. If either i or j
is a negative value, it is interpreted the same as selecting a character by
counting from the end of the string. Hence, a value of -1 is the same as
selecting the last character of the string.
If the requested indices are out of range for the given string, an error is
reported.
]]
function str.sub( frame )
local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } );
local s = new_args['s'] or '';
local i = tonumber( new_args['i'] ) or 1;
local j = tonumber( new_args['j'] ) or -1;
local len = mw.ustring.len( s );
-- Convert negatives for range checking
if i < 0 then
i = len + i + 1;
end
if j < 0 then
j = len + j + 1;
end
if i > len or j > len or i < 1 or j < 1 then
return str._error( 'Значение индекса подстроки выходит за допустимые границы' );
end
if j < i then
return str._error( 'Неверный порядок индексов подстроки' );
end
return mw.ustring.sub( s, i, j )
end
--[[
This function implements that features of {{str sub old}} and is kept in order
to maintain these older templates.
]]
function str.sublength( frame )
local i = tonumber( frame.args.i ) or 0
local len = tonumber( frame.args.len )
return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) )
end
--[[
match
This function returns a substring from the source string that matches a
specified pattern.
Usage:
{{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}}
OR
{{#invoke:String|pos|s=source_string|pattern=pattern_string|start=start_index
|match=match_number|plain=plain_flag|nomatch=nomatch_output}}
Parameters
s: The string to search
pattern: The pattern or string to find within the string
start: The index within the source string to start the search. The first
character of the string has index 1. Defaults to 1.
match: In some cases it may be possible to make multiple matches on a single
string. This specifies which match to return, where the first match is
match= 1. If a negative number is specified then a match is returned
counting from the last match. Hence match = -1 is the same as requesting
the last match. Defaults to 1.
plain: A flag indicating that the pattern should be understood as plain
text. Defaults to false.
nomatch: If no match is found, output the "nomatch" value rather than an error.
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from each string. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
If the match_number or start_index are out of range for the string being queried, then
this function generates an error. An error is also generated if no match is found.
If one adds the parameter ignore_errors=true, then the error will be suppressed and
an empty string will be returned on any failure.
For information on constructing Lua patterns, a form of [regular expression], see:
* http://www.lua.org/manual/5.1/manual.html#5.4.1
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns
]]
function str.match( frame )
local new_args = str._getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} );
local s = new_args['s'] or '';
local start = tonumber( new_args['start'] ) or 1;
local plain_flag = str._getBoolean( new_args['plain'] or false );
local pattern = new_args['pattern'] or '';
local match_index = math.floor( tonumber(new_args['match']) or 1 );
local nomatch = new_args['nomatch'];
if s == '' then
return str._error( 'Пустая строка поиска' );
end
if pattern == '' then
return str._error( 'Пустой шаблон поиска' );
end
if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then
return str._error( 'Индекс начала поиска выходит за допустимые границы' );
end
if match_index == 0 then
return str._error( 'Индекс совпадения выходит за допустимые границы' );
end
if plain_flag then
pattern = str._escapePattern( pattern );
end
local result
if match_index == 1 then
-- Find first match is simple case
result = mw.ustring.match( s, pattern, start )
else
if start > 1 then
s = mw.ustring.sub( s, start );
end
local iterator = mw.ustring.gmatch(s, pattern);
if match_index > 0 then
-- Forward search
for w in iterator do
match_index = match_index - 1;
if match_index == 0 then
result = w;
break;
end
end
else
-- Reverse search
local result_table = {};
local count = 1;
for w in iterator do
result_table[count] = w;
count = count + 1;
end
result = result_table[ count + match_index ];
end
end
if result == nil then
if nomatch == nil then
return str._error( 'Совпадение не найдено' );
else
return nomatch;
end
else
return result;
end
end
--[[
pos
This function returns a single character from the target string at position pos.
Usage:
{{#invoke:String|pos|target_string|index_value}}
OR
{{#invoke:String|pos|target=target_string|pos=index_value}}
Parameters
target: The string to search
pos: The index for the character to return
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
The first character has an index value of 1.
If one requests a negative value, this function will select a character by counting backwards
from the end of the string. In other words pos = -1 is the same as asking for the last character.
A requested value of zero, or a value greater than the length of the string returns an error.
]]
function str.pos( frame )
local new_args = str._getParameters( frame.args, {'target', 'pos'} );
local target_str = new_args['target'] or '';
local pos = tonumber( new_args['pos'] ) or 0;
if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then
return str._error( 'Значение индекса строки выходит за допустимые границы' );
end
return mw.ustring.sub( target_str, pos, pos );
end
--[[
str_find
This function duplicates the behavior of {{str_find}}, including all of its quirks.
This is provided in order to support existing templates, but is NOT RECOMMENDED for
new code and templates. New code is recommended to use the "find" function instead.
Returns the first index in "source" that is a match to "target". Indexing is 1-based,
and the function returns -1 if the "target" string is not present in "source".
Important Note: If the "target" string is empty / missing, this function returns a
value of "1", which is generally unexpected behavior, and must be accounted for
separatetly.
]]
function str.str_find( frame )
local new_args = str._getParameters( frame.args, {'source', 'target'} );
local source_str = new_args['source'] or '';
local target_str = new_args['target'] or '';
if target_str == '' then
return 1;
end
local start = mw.ustring.find( source_str, target_str, 1, true )
if start == nil then
start = -1
end
return start
end
--[[
find
This function allows one to search for a target string or pattern within another
string.
Usage:
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}}
OR
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}}
Parameters
source: The string to search
target: The string or pattern to find within source
start: The index within the source string to start the search, defaults to 1
plain: Boolean flag indicating that target should be understood as plain
text and not as a Lua style regular expression, defaults to true
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the parameter. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
This function returns the first index >= "start" where "target" can be found
within "source". Indices are 1-based. If "target" is not found, then this
function returns 0. If either "source" or "target" are missing / empty, this
function also returns 0.
This function should be safe for UTF-8 strings.
]]
function str.find( frame )
local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } );
local source_str = new_args['source'] or '';
local pattern = new_args['target'] or '';
local start_pos = tonumber(new_args['start']) or 1;
local plain = new_args['plain'] or true;
if source_str == '' or pattern == '' then
return 0;
end
plain = str._getBoolean( plain );
local start = mw.ustring.find( source_str, pattern, start_pos, plain )
if start == nil then
start = 0
end
return start
end
--[[
replace
This function allows one to replace a target string or pattern within another
string.
Usage:
{{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}}
OR
{{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string|
count=replacement_count|plain=plain_flag}}
Parameters
source: The string to search
pattern: The string or pattern to find within source
replace: The replacement text
count: The number of occurences to replace, defaults to all.
plain: Boolean flag indicating that pattern should be understood as plain
text and not as a Lua style regular expression, defaults to true
]]
function str.replace( frame )
local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } );
local source_str = new_args['source'] or '';
local pattern = new_args['pattern'] or '';
local replace = new_args['replace'] or '';
local count = tonumber( new_args['count'] );
local plain = new_args['plain'] or true;
if source_str == '' or pattern == '' then
return source_str;
end
plain = str._getBoolean( plain );
if plain then
pattern = str._escapePattern( pattern );
replace = string.gsub( replace, "%%", "%%%%" ) --Only need to escape replacement sequences.
end
local result;
if count ~= nil then
result = mw.ustring.gsub( source_str, pattern, replace, count );
else
result = mw.ustring.gsub( source_str, pattern, replace );
end
return result;
end
--[[
This function adds support for escaping parts of the patterns when using [plain=false].
]]
function str.escape( frame )
local new_args = str._getParameters( frame.args, {'pattern' } );
local pattern = new_args['pattern'] or '';
local result = '';
result = str._escapePattern( pattern );
return result;
end
--[[
Internal compare string function
]]
function str._strcmp(a , b)
local s1c = mw.ustring.gcodepoint( a );
local s2c = mw.ustring.gcodepoint( b );
while true do
local c1 = s1c();
local c2 = s2c();
if c1 == nil then
if c2 == nil then
return 0
else
return -1
end
else
if c2 ~= nil then
if c1 ~= c2 then
return c1 < c2 and -1 or 1
end
else
return 1
end
end
end
return 0
end
--[[
compare
This function compare two UTF-8 strings
Usage:
{{#invoke:String|compare|str1|str2}}
Returns:
0 - if strings are equal
1 - if st1 > str2
-1 - if str1 < str2
]]
function str.compare(frame)
local str1 = frame.args[1] or '';
local str2 = frame.args[2] or '';
return str._strcmp(str1 , str2)
end
--[[
simple function to pipe string.rep to templates.
]]
function str.rep( frame )
local repetitions = tonumber( frame.args[2] )
if not repetitions then
return str._error( 'функция rep ожидает число во втором параметре, а получено "' .. ( frame.args[2] or '' ) .. '"' )
end
return string.rep( frame.args[1] or '', repetitions )
end
--[[
Helper function that populates the argument list given that user may need to use a mix of
named and unnamed parameters. This is relevant because named parameters are not
identical to unnamed parameters due to string trimming, and when dealing with strings
we sometimes want to either preserve or remove that whitespace depending on the application.
]]
function str._getParameters( frame_args, arg_list )
local new_args = {};
local index = 1;
local value;
for i,arg in ipairs( arg_list ) do
value = frame_args[arg]
if value == nil then
value = frame_args[index];
index = index + 1;
end
new_args[arg] = value;
end
return new_args;
end
--[[
Helper function to handle error messages.
]]
function str._error( error_str )
local frame = mw.getCurrentFrame();
local error_category = frame.args.error_category or 'Страницы с ошибками модуля String';
local ignore_errors = frame.args.ignore_errors or false;
local no_category = frame.args.no_category or false;
if str._getBoolean(ignore_errors) then
return '';
end
local error_str = '<strong class="error">Ошибка модуля String: ' .. error_str .. '</strong>';
if error_category ~= '' and not str._getBoolean( no_category ) then
error_str = '[[Категория:' .. error_category .. ']]' .. error_str;
end
return error_str;
end
--[[
Helper Function to interpret boolean strings
]]
function str._getBoolean( boolean_str )
local boolean_value;
if type( boolean_str ) == 'string' then
boolean_str = boolean_str:lower();
if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0'
or boolean_str == '' then
boolean_value = false;
else
boolean_value = true;
end
elseif type( boolean_str ) == 'boolean' then
boolean_value = boolean_str;
else
error( 'Логическое значение не найдено' );
end
return boolean_value
end
--[[
Helper function that escapes all pattern characters so that they will be treated
as plain text.
]]
function str._escapePattern( pattern_str )
return ( string.gsub( pattern_str, "[%(%)%.%%%+%-%*%?%[%^%$%]]", "%%%0" ) )
end
return str
2c7347f1dafbbc0efc196c148a1f81e7b82420dc
Модуль:TemplateDataDoc
828
103
203
2024-11-22T13:56:09Z
wikipedia:ru>Stjn
0
для примеров всё-таки не нужно
Scribunto
text/plain
require( 'strict' );
local docSubPage = mw.message.new( 'Templatedata-doc-subpage' ):plain();
local p = {};
local lastNumber = 0;
-- Enable/disable additional spacing for block-formatted templates
local formatBlockSpaces = true;
-- Params that should not be shown in code
local deprecatedParams = {
'nocat',
'from',
'nocoord',
'nocatcoord',
'Автооформление заголовка',
'автооформление заголовка',
'Ширина',
'ширина',
'Ширина изображения',
'ширина изображения',
'Ширина логотипа',
'ширина логотипа',
'Ширина автографа',
'ширина автографа',
};
local noDocNote = 'TemplateDataDoc: Запишите страницу для отображения заполненного шаблона.';
function p.processJson( json )
local status, data = pcall( mw.text.jsonDecode, json );
if status == false then
return nil;
end
if not data[ 'paramOrder' ] then
data[ 'paramOrder' ] = {};
for paramName, paramData in pairs( data[ 'params' ] ) do
table.insert( data[ 'paramOrder' ], paramName );
end
end
for _, param in ipairs( deprecatedParams ) do
if data[ 'params' ][ param ] ~= nil then
data[ 'params' ][ param ][ 'deprecated' ] = '-';
end
end
return data;
end
function p.getTemplateData( pageName )
local title = mw.title.makeTitle( 0, pageName );
if not title or not title.exists then
return false
end
local content = title:getContent()
if not content then
return false;
end;
local json = mw.ustring.match( content, '<[Tt]emplate[Dd]ata%s*>(.*)</[Tt]emplate[Dd]ata%s*>' );
if not json then
return nil;
end
return p.processJson( json )
end
function p.getValue( data, key )
if data[ key ] then
return data[ key ];
end
-- Numbered keys return as numbers
local nkey = tonumber( key );
if nkey ~= nil and data[ nkey ] then
return data[ nkey ];
end
return {};
end
-- See https://phabricator.wikimedia.org/diffusion/ETDA/browse/master/Specification.md?as=remarkup
-- We need a global format value for the 'block' and 'inline': [[phab:T205438]]
function p.convertFormatString( rawTemplateFormat )
local formatType = rawTemplateFormat or 'inline';
local templateFormat = formatType;
local isBlockFormatted = false;
if formatType == 'block' then
templateFormat = '{{_\n| _ = _\n}}';
isBlockFormatted = true;
elseif formatType == 'inline' then
templateFormat = '{{_|_=_}}';
end
return templateFormat, isBlockFormatted, formatType;
end
function p.getFormatParts( rawTemplateFormat, templateName )
local templateFormat, isBlockFormatted, formatType = p.convertFormatString( rawTemplateFormat );
local nameFormat = mw.ustring.match( templateFormat, '^[^|]+' );
local paramKeyFormat = mw.ustring.match( templateFormat, '%|[^=]+=' );
local paramValueFormat = mw.ustring.match( templateFormat, '=[^}]+' );
paramValueFormat = mw.ustring.sub( paramValueFormat, 2 );
local endFormat = mw.ustring.match( templateFormat, '%}%}.*$' );
local startFormat = mw.ustring.gsub( nameFormat, '_', templateName );
return isBlockFormatted, formatType, startFormat, endFormat, paramKeyFormat, paramValueFormat;
end
function p.formatKeyValue( key, parameterData, formatData )
if parameterData[ 'deprecated' ] then
return '';
end
local args = formatData.args;
local parameterName = key;
local nkey = tonumber( key );
-- Add additional spacing to string keys
if formatBlockSpaces and formatData.parameterLength and formatData.formatType ~= 'inline' and ( nkey == nil or lastNumber ~= nkey - 1 ) then
while mw.ustring.len( key ) < formatData.parameterLength do
key = key .. ' ';
end
end
-- Remove numbering for adjacent numbered keys
if nkey ~= nil and lastNumber == nkey - 1 then
key = '';
lastNumber = nkey;
end
local value = '';
if formatData.valueKey == 'example' and parameterData[ 'example' ] then
-- Example
value = parameterData[ 'example' ];
else
if formatData.valueKey == 'description' and parameterData[ 'description' ] then
-- Description
value = parameterData[ 'description' ];
if value ~= '' then
value = '<!-- ' .. value .. ' -->';
end
elseif parameterData[ 'autovalue' ] then
-- Autovalue
value = parameterData[ 'autovalue' ];
end
if args[ '$' .. parameterName ] and args[ '$' .. parameterName ] ~= '' then
-- Custom values from template call
value = args[ '$' .. parameterName ];
end
end
local formattedKey = mw.ustring.gsub( formatData.paramKeyFormat, '_+', key, 1 );
if key == '' then
formattedKey = mw.ustring.gsub( formattedKey, '=', '' );
end
return formattedKey .. mw.ustring.gsub( formatData.paramValueFormat, '_', value, 1 );
end
function p.generateBlankCode( templateData, templateName, args )
if templateData == false then
return '{{' .. templateName .. '}}';
end
local parameterLength = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = p.getValue( templateData[ 'params' ], parameterName );
if not parameterData[ 'deprecated' ] then
local length = mw.ustring.len( parameterName );
if length > parameterLength then
parameterLength = length;
end
end
end
local isBlockFormatted, formatType, startFormat, endFormat, paramKeyFormat, paramValueFormat = p.getFormatParts( templateData[ 'format' ], templateName );
local out = startFormat;
lastNumber = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = p.getValue( templateData[ 'params' ], parameterName );
if parameterData[ 'inherits' ] then
parameterData = p.getValue( templateData[ 'params' ], parameterData[ 'inherits' ] );
end
out = out .. p.formatKeyValue( parameterName, parameterData, {
args = args,
valueKey = ( args[ 'description' ] and 'description' or nil ),
formatType = formatType,
isBlockFormatted = isBlockFormatted,
parameterLength = parameterLength,
paramKeyFormat = paramKeyFormat,
paramValueFormat = paramValueFormat,
} );
end
return out .. endFormat;
end
function p.generateBlank( frame )
local frame = mw.getCurrentFrame();
local getArgs = require( 'Module:Arguments' ).getArgs;
local args = getArgs( frame );
local templateName = frame.args[ 1 ];
table.remove( args, 1 );
local docPage = 'Template:' .. templateName .. '/' .. docSubPage;
local templateData = p.getTemplateData( docPage );
local out = p.generateBlankCode( templateData, templateName, args );
local previewNote = ''
if templateData == false and frame:preprocess('{{REVISIONID}}') == '' then
previewNote = '<div class="warningbox">' .. noDocNote .. '</div>';
end
return previewNote .. frame:extensionTag{
name = 'syntaxhighlight',
args = { lang = 'html', copy = true },
content = out,
};
end
function p.generateExampleCode( templateData, templateName, args )
if templateData == false then
return '{{' .. templateName .. '}}';
end
local parameterLength = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = p.getValue( templateData[ 'params' ], parameterName );
if parameterData[ 'example' ] and not parameterData[ 'deprecated' ] then
local length = mw.ustring.len( parameterName );
if length > parameterLength then
parameterLength = length;
end
end
end
local isBlockFormatted, formatType, startFormat, endFormat, paramKeyFormat, paramValueFormat = p.getFormatParts( templateData[ 'format' ], templateName );
local out = startFormat;
lastNumber = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = p.getValue( templateData[ 'params' ], parameterName );
if parameterData[ 'inherits' ] then
parameterData = p.getValue( templateData[ 'params' ], parameterData[ 'inherits' ] );
end
if parameterData[ 'example' ] then
out = out .. p.formatKeyValue( parameterName, parameterData, {
args = args,
valueKey = 'example',
formatType = formatType,
isBlockFormatted = isBlockFormatted,
parameterLength = parameterLength,
paramKeyFormat = paramKeyFormat,
paramValueFormat = paramValueFormat,
} );
end
end
return out .. endFormat;
end
function p.generateExample( frame )
local frame = mw.getCurrentFrame();
local args = frame.args;
local templateName = frame.args[ 1 ];
local docPage = 'Template:' .. templateName .. '/' .. docSubPage;
local templateData = p.getTemplateData( docPage );
local out = p.generateExampleCode( templateData, templateName, args );
local previewNote = ''
if templateData == false and frame:preprocess('{{REVISIONID}}') == '' then
previewNote = '<div class="warningbox">' .. noDocNote .. '</div>';
end
return previewNote .. frame:preprocess( out ) .. frame:extensionTag{
name = 'syntaxhighlight',
args = { lang = 'html' },
content = out,
};
end
return p;
8134c68a67c62ea08db535b9110981288d627bbd
Модуль:Wikidata/config
828
34
65
2024-12-15T07:54:37Z
wikipedia:ru>Putnik
0
на всякий случай, чтобы избежать ненужных сносок
Scribunto
text/plain
-- Property configuration for Wikidata module
return {
global = {
separator = ', ',
conjunction = ' и ',
},
presets = {
['catonly'] = {
datatype = 'wikibase-item',
conjunction = '',
invisible = true,
['value-module'] = 'Wikidata/item',
['value-function'] = 'formatCategoryOnly',
references = '',
category = 'P910',
},
['country'] = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/Places',
['claim-function'] = 'formatCountryClaimWithFlag',
before = '<ul><li>',
separator = '</li><li>',
conjunction = '</li><li>',
after = '</li></ul>',
},
['from-to'] = {
datatype = 'time',
['property-module'] = 'Wikidata/date',
['property-function'] = 'formatDateIntervalProperty',
},
['link'] = {
['value-module'] = 'Wikidata/link',
['value-function'] = 'fromModule',
},
['list'] = {
before = '<ul><li>',
separator = '</li><li>',
conjunction = '</li><li>',
after = '</li></ul>',
},
['name'] = {
datatype = 'monolingualtext',
monolingualLangTemplate = 'lang',
separator = '<br>',
conjunction = '<br>',
},
['place'] = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/Places',
['claim-function'] = 'formatPlaceWithQualifiers',
before = '<ul><li>',
separator = '</li><li>',
conjunction = '</li><li>',
after = '</li></ul>',
},
['quantity (date)'] = {
datatype = 'quantity',
before = '<ul><li>',
separator = '</li><li>',
conjunction = '</li><li>',
after = '</li></ul>',
qualifier = 'P585',
},
},
datatypes = {
commonsMedia = {
limit = 1,
references = false,
size = '274x400px',
separator = '<br>',
conjunction = '<br>',
somevalue = '',
['value-module'] = 'Wikidata/media',
['value-function'] = 'formatCommonsMediaValue',
},
['external-id'] = {
references = false,
},
['globe-coordinate'] = {
limit = 1,
references = false,
},
url = {
separator = '<br>',
conjunction = '<br>',
references = false,
['value-module'] = 'Wikidata/url',
['value-function'] = 'formatUrlValue',
},
quantity = {
siConversion = true
}
},
properties = {
P6 = { datatype = 'wikibase-item', },
P17 = {
preset = 'country',
},
P18 = {
datatype = 'commonsMedia',
fixdouble = true,
},
P19 = {
preset = 'place',
separator = ',</li><li>',
conjunction = ' или </li><li>',
},
P20 = {
preset = 'place',
separator = ',</li><li>',
conjunction = ' или </li><li>',
},
P22 = {
datatype = 'wikibase-item',
conjunction = ' или '
},
P25 = {
datatype = 'wikibase-item',
conjunction = ' или '
},
P26 = { datatype = 'wikibase-item', },
P27 = {
preset = 'country',
},
P31 = {
datatype = 'wikibase-item',
references = false,
},
P37 = { datatype = 'wikibase-item', },
P39 = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/positions',
['claim-function'] = 'formatPositionClaim',
separator = '',
conjunction = '',
allowTables = true,
},
P40 = { datatype = 'wikibase-item', },
P41 = {
datatype = 'commonsMedia',
size = '150x200px',
},
P53 = {
datatype = 'wikibase-item',
category = 'P910',
},
P54 = {
category = 'P6112',
},
P57 = {
datatype = 'wikibase-item',
preset = 'list',
},
P58 = {
datatype = 'wikibase-item',
preset = 'list',
},
P59 = {
datatype = 'wikibase-item',
category = 'P910',
references = false,
},
P69 = {
datatype = 'wikibase-item',
preset = 'list',
category = 'P3876',
qualifier = 'P582',
},
P94 = {
datatype = 'commonsMedia',
size = '100x200px',
},
P86 = {
datatype = 'wikibase-item',
preset = 'list',
},
P101 = { datatype = 'wikibase-item', },
P102 = {
datatype = 'wikibase-item',
preset = 'list',
qualifier = 'P582',
category = 'P6365',
},
P103 = { datatype = 'wikibase-item', },
P106 = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/item',
['claim-function'] = 'formatEntityWithGenderClaim',
conjunction = ', ',
},
P108 = {
datatype = 'wikibase-item',
preset = 'list',
category = 'P4195',
},
P109 = {
datatype = 'commonsMedia',
size = '150x150px',
alt = 'Изображение автографа',
},
P117 = {
datatype = 'commonsMedia',
size = '290x300px',
alt = 'Изображение химической структуры',
},
P119 = {
preset = 'place',
thisLocationOnly = 'true',
},
P131 = { datatype = 'wikibase-item', },
P140 = {
datatype = 'wikibase-item',
},
P154 = {
size = '220x80px',
alt = 'Изображение логотипа',
},
P159 = {
preset = 'place',
},
P161 = {
preset = 'list',
},
P162 = {
preset = 'list',
},
P163 = { datatype = 'wikibase-item', },
P166 = {
datatype = 'wikibase-item',
['property-module'] = 'Wikidata/Medals',
['property-function'] = 'formatProperty',
['value-module'] = 'Wikidata/Medals',
['value-function'] = 'formatValue',
before = '<div style="text-align:justify">',
after = '</div>',
separator = ' ',
conjunction = ' ',
references = false,
allowTables = true,
},
P190 = { datatype = 'wikibase-item', },
P212 = {
preset = 'link',
},
P225 = {
preset = 'list',
['claim-module'] = 'Wikidata/Biology',
['claim-function'] = 'formatTaxonNameClaim',
},
P237 = { datatype = 'wikibase-item', },
P241 = { datatype = 'wikibase-item', },
P242 = {
datatype = 'commonsMedia',
size = '300x300px',
},
P247 = {
formatter = 'https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id=$1',
},
P267 = {
preset = 'link',
},
P276 = {
preset = 'place',
},
P281 = { datatype = 'string', },
P286 = {
preset = 'list',
},
P296 = {
formatter = 'http://osm.sbin.ru/esr/esr:$1',
},
P301 = {
rawArticle = true,
},
P344 = {
preset = 'list',
},
P345 = {
preset = 'link',
},
P348 = {
preset = 'list',
['property-module'] = 'Wikidata/Software',
['property-function'] = 'formatVersionProperty',
},
P361 = { datatype = 'wikibase-item', },
P373 = {
datatype = 'string',
['value-module'] = 'Wikidata/media',
['value-function'] = 'formatCommonsCategory',
limit = 1,
references = false,
},
P374 = { datatype = 'external-id', },
P395 = { datatype = 'string', },
P407 = { datatype = 'wikibase-item', },
P410 = { datatype = 'wikibase-item', },
P412 = {
datatype = 'wikibase-item',
category = 'P910',
},
P413 = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/item',
['claim-function'] = 'formatEntityWithGenderClaim',
conjunction = ', ',
category = 'P910',
},
P414 = {
['claim-module'] = 'Wikidata/item',
['claim-function'] = 'applyDefaultTemplate',
},
P421 = { datatype = 'wikibase-item', },
P473 = { datatype = 'string', },
P495 = {
preset = 'country',
},
P505 = {
preset = 'list',
},
P512 = {
datatype = 'wikibase-item',
['property-module'] = 'Wikidata/P512',
['property-function'] = 'formatAcademicDegree',
},
P527 = {
preset = 'list',
},
P528 = {
references = false,
qualifier = 'P972',
},
P551 = {
preset = 'place',
},
P569 = {
datatype = 'time',
['claim-module'] = 'Wikidata/date',
['claim-function'] = 'formatDateOfBirthClaim',
},
P570 = {
datatype = 'time',
['claim-module'] = 'Wikidata/date',
['claim-function'] = 'formatDateOfDeathClaim',
},
P571 = { datatype = 'time', },
P576 = { datatype = 'time', },
P598 = { datatype = 'wikibase-item', },
P607 = {
datatype = 'wikibase-item',
preset = 'list',
},
P625 = { datatype = 'globe-coordinate', },
P669 = {
qualifier = 'P670',
},
P685 = {
formatter = 'https://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id=$1',
},
P721 = {
preset = 'link',
},
P764 = {
preset = 'link',
},
P803 = { datatype = 'wikibase-item', },
P856 = { datatype = 'url', },
P881 = {
novalue = 'нет',
category = 'P910',
},
P884 = {
preset = 'link',
},
P915 = {
category = 'P1740',
},
P957 = {
preset = 'link',
},
P972 = {
preset = 'catonly',
},
P1077 = {
preset = 'link',
},
P1082 = {
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P1098 = {
preset = 'quantity (date)',
unit = 'чел.',
},
P1120 = {
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P1128 = {
datatype = 'quantity',
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P1114 = {
datatype = 'quantity',
qualifier = 'P585',
},
P1174 = {
preset = 'quantity (date)',
unit = 'чел.',
},
P1195 = {
['value-module'] = 'Wikidata/Software',
['value-function'] = 'formatExtension',
conjunction = ' или ',
},
P1215 = {
datatype = 'quantity',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatVisualMagnitude'
},
P1246 = {
preset = 'link',
},
P1249 = { datatype = 'time', },
P1352 = { preset = 'quantity (date)', },
P1376 = { datatype = 'wikibase-item', },
P1402 = {
preset = 'link',
},
P1448 = {
preset = 'name',
},
P1458 = {
datatype = 'quantity',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatColorIndex'
},
P1464 = { datatype = 'wikibase-item', },
P1476 = {
preset = 'name',
},
P1477 = {
preset = 'name',
},
P1532 = {
preset = 'country',
rank = '[rank:normal, rank:preferred]',
},
P1543 = {
datatype = 'commonsMedia',
},
P1559 = {
preset = 'name',
},
P1603 = {
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P1621 = {
size = '300x300px',
},
P1692 = {
preset = 'link',
},
P1705 = {
preset = 'name',
},
P1753 = {
rowArticle = true,
},
P1809 = {
preset = 'list',
},
P1846 = {
datatype = 'commonsMedia',
fixdouble = true,
},
P2031 = {
preset = 'from-to',
to = 'P2032',
within = 'P570',
},
P2043 = {
preset = 'quantity (date)',
},
P2044 = { datatype = 'quantity', },
P2046 = {
preset = 'quantity (date)',
siConversion = false,
},
P2047 = {
siConversion = false,
},
P2048 = {
conjunction = ' или ',
},
P2060 = {
siConversion = false,
},
P2097 = {
siConversion = false,
},
P2120 = {
siConversion = false,
},
P2137 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2139 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2146 = {
siConversion = false,
},
P2214 = {
siConversion = false
},
P2226 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2257 = {
siConversion = false
},
P2260 = {
siConversion = false
},
P2295 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2324 = {
datatype = 'quantity',
preset = 'quantity (date)',
unit = 'чел.'
},
P2403 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2425 = {
alt = 'Изображение орденской планки',
},
P2583 = {
siConversion = false,
},
P2597 = {
preset = 'catonly',
},
P2650 = { datatype = 'wikibase-item', },
P2789 = {
preset = 'list',
},
P2896 = {
siConversion = false,
},
P2910 = {
size = '100x80px',
},
P3083 = {
formatter = 'http://simbad.u-strasbg.fr/simbad/sim-id?Ident=$1',
},
P3086 = {
siConversion = false,
},
P3362 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P4614 = {
category = 'P1200',
},
P5348 = {
siConversion = false,
},
P6257 = {
['value-module'] = 'Wikidata/number',
['value-function'] = 'formatRA',
},
P6258 = {
['value-module'] = 'Wikidata/number',
['value-function'] = 'formatDMS',
},
P6259 = {
['references'] = false,
},
P7584 = {
siConversion = false,
},
P8010 = {
datatype = 'quantity',
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P8224 = {
alt = 'Изображение молекулярной модели',
},
},
categories = {
['links-to-entities-with-missing-label'] = 'Википедия:Статьи со ссылками на элементы Викиданных без подписи',
['links-to-entities-with-wikibase-error'] = 'Википедия:Страницы с ошибками скриптов, использующих Викиданные',
['links-to-entities-with-missing-local-language-label'] = 'Википедия:Статьи со ссылками на элементы Викиданных без русской подписи',
['media-contains-local-caption'] = 'Википедия:Локальная подпись у изображения из Викиданных',
['media-contains-markup'] = 'Википедия:Статьи с вики-разметкой в изображении карточки',
['media-contains-local-double'] = 'Википедия:Изображение в статье дублирует изображение в карточке',
['value-contains-table'] = 'Википедия:Статьи с табличной вставкой в карточке',
},
errors = {
['property-param-not-provided'] = 'Не дан параметр свойства',
['entity-not-found'] = 'Сущность не найдена.',
['unknown-claim-type'] = 'Неизвестный тип заявления.',
['unknown-snak-type'] = 'Неизвестный тип снэка.',
['unknown-datavalue-type'] = 'Неизвестный тип значения данных.',
['unknown-entity-type'] = 'Неизвестный тип сущности.',
['unknown-property-module'] = 'Вы должны установить и property-module, и property-function.',
['unknown-claim-module'] = 'Вы должны установить и claim-module, и claim-function.',
['unknown-value-module'] = 'Вы должны установить и value-module, и value-function.',
['property-module-not-found'] = 'Модуль для отображения свойства не найден',
['property-function-not-found'] = 'Функция для отображения свойства не найдена',
['claim-module-not-found'] = 'Модуль для отображения утверждения не найден.',
['claim-function-not-found'] = 'Функция для отображения утверждения не найдена.',
['value-module-not-found'] = 'Модуль для отображения значения не найден.',
['value-function-not-found'] = 'Функция для отображения значения не найдена.',
},
i18n = {
somevalue = "''неизвестно''",
novalue = '',
-- Обстоятельства источника
Q5727902 = 'около ',
Q18122778 = '<span style="border-bottom: 1px dotted; cursor: help;" title="предположительно">предп.</span> ',
Q30230067 = 'возможно ',
Q52834024 = '<span style="border-bottom: 1px dotted; cursor: help;" title="менее чем"><</span> ',
Q54418095 = '<span style="border-bottom: 1px dotted; cursor: help;" title="более чем">></span> ',
Q60070514 = 'примерно ',
thousandPowers = {'', ' тыс.', ' млн', ' млрд', ' трлн'},
},
deprecatedSources = {
Q355 = true, -- Facebook
Q36578 = true, -- Gemeinsame Normdatei
Q63056 = true, -- Find a Grave
Q212256 = true, -- АиФ
Q504063 = true, -- Discogs
Q523660 = true, -- International Music Score Library Project by https://ru.wikipedia.org/?diff=107090748
Q1798125 = true, -- LIBRIS
Q2621214 = true, -- Geni
Q15222191 = true, -- BNF
Q15241312 = true, -- Freebase
Q19938912 = true, -- BNF
Q21697707 = true, -- Хайазг
Q25328680 = true, -- Prabook
Q29861311 = true, -- SNAC
Q86999151 = true, -- WeChangEd
},
};
bd6091486f675bebf109cb52de53a162b05a5243
66
65
2025-01-25T21:00:18Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- Property configuration for Wikidata module
return {
global = {
separator = ', ',
conjunction = ' и ',
},
presets = {
['catonly'] = {
datatype = 'wikibase-item',
conjunction = '',
invisible = true,
['value-module'] = 'Wikidata/item',
['value-function'] = 'formatCategoryOnly',
references = '',
category = 'P910',
},
['country'] = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/Places',
['claim-function'] = 'formatCountryClaimWithFlag',
before = '<ul><li>',
separator = '</li><li>',
conjunction = '</li><li>',
after = '</li></ul>',
},
['from-to'] = {
datatype = 'time',
['property-module'] = 'Wikidata/date',
['property-function'] = 'formatDateIntervalProperty',
},
['link'] = {
['value-module'] = 'Wikidata/link',
['value-function'] = 'fromModule',
},
['list'] = {
before = '<ul><li>',
separator = '</li><li>',
conjunction = '</li><li>',
after = '</li></ul>',
},
['name'] = {
datatype = 'monolingualtext',
monolingualLangTemplate = 'lang',
separator = '<br>',
conjunction = '<br>',
},
['place'] = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/Places',
['claim-function'] = 'formatPlaceWithQualifiers',
before = '<ul><li>',
separator = '</li><li>',
conjunction = '</li><li>',
after = '</li></ul>',
},
['quantity (date)'] = {
datatype = 'quantity',
before = '<ul><li>',
separator = '</li><li>',
conjunction = '</li><li>',
after = '</li></ul>',
qualifier = 'P585',
},
},
datatypes = {
commonsMedia = {
limit = 1,
references = false,
size = '274x400px',
separator = '<br>',
conjunction = '<br>',
somevalue = '',
['value-module'] = 'Wikidata/media',
['value-function'] = 'formatCommonsMediaValue',
},
['external-id'] = {
references = false,
},
['globe-coordinate'] = {
limit = 1,
references = false,
},
url = {
separator = '<br>',
conjunction = '<br>',
references = false,
['value-module'] = 'Wikidata/url',
['value-function'] = 'formatUrlValue',
},
quantity = {
siConversion = true
}
},
properties = {
P6 = { datatype = 'wikibase-item', },
P17 = {
preset = 'country',
},
P18 = {
datatype = 'commonsMedia',
fixdouble = true,
},
P19 = {
preset = 'place',
separator = ',</li><li>',
conjunction = ' или </li><li>',
},
P20 = {
preset = 'place',
separator = ',</li><li>',
conjunction = ' или </li><li>',
},
P22 = {
datatype = 'wikibase-item',
conjunction = ' или '
},
P25 = {
datatype = 'wikibase-item',
conjunction = ' или '
},
P26 = { datatype = 'wikibase-item', },
P27 = {
preset = 'country',
},
P31 = {
datatype = 'wikibase-item',
references = false,
},
P37 = { datatype = 'wikibase-item', },
P39 = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/positions',
['claim-function'] = 'formatPositionClaim',
separator = '',
conjunction = '',
allowTables = true,
},
P40 = { datatype = 'wikibase-item', },
P41 = {
datatype = 'commonsMedia',
size = '150x200px',
},
P53 = {
datatype = 'wikibase-item',
category = 'P910',
},
P54 = {
category = 'P6112',
},
P57 = {
datatype = 'wikibase-item',
preset = 'list',
},
P58 = {
datatype = 'wikibase-item',
preset = 'list',
},
P59 = {
datatype = 'wikibase-item',
category = 'P910',
references = false,
},
P69 = {
datatype = 'wikibase-item',
preset = 'list',
category = 'P3876',
qualifier = 'P582',
},
P94 = {
datatype = 'commonsMedia',
size = '100x200px',
},
P86 = {
datatype = 'wikibase-item',
preset = 'list',
},
P101 = { datatype = 'wikibase-item', },
P102 = {
datatype = 'wikibase-item',
preset = 'list',
qualifier = 'P582',
category = 'P6365',
},
P103 = { datatype = 'wikibase-item', },
P106 = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/item',
['claim-function'] = 'formatEntityWithGenderClaim',
conjunction = ', ',
},
P108 = {
datatype = 'wikibase-item',
preset = 'list',
category = 'P4195',
},
P109 = {
datatype = 'commonsMedia',
size = '150x150px',
alt = 'Изображение автографа',
},
P117 = {
datatype = 'commonsMedia',
size = '290x300px',
alt = 'Изображение химической структуры',
},
P119 = {
preset = 'place',
thisLocationOnly = 'true',
},
P131 = { datatype = 'wikibase-item', },
P140 = {
datatype = 'wikibase-item',
},
P154 = {
size = '220x80px',
alt = 'Изображение логотипа',
},
P159 = {
preset = 'place',
},
P161 = {
preset = 'list',
},
P162 = {
preset = 'list',
},
P163 = { datatype = 'wikibase-item', },
P166 = {
datatype = 'wikibase-item',
['property-module'] = 'Wikidata/Medals',
['property-function'] = 'formatProperty',
['value-module'] = 'Wikidata/Medals',
['value-function'] = 'formatValue',
before = '<div style="text-align:justify">',
after = '</div>',
separator = ' ',
conjunction = ' ',
references = false,
allowTables = true,
},
P190 = { datatype = 'wikibase-item', },
P212 = {
preset = 'link',
},
P225 = {
preset = 'list',
['claim-module'] = 'Wikidata/Biology',
['claim-function'] = 'formatTaxonNameClaim',
},
P237 = { datatype = 'wikibase-item', },
P241 = { datatype = 'wikibase-item', },
P242 = {
datatype = 'commonsMedia',
size = '300x300px',
},
P247 = {
formatter = 'https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id=$1',
},
P267 = {
preset = 'link',
},
P276 = {
preset = 'place',
},
P281 = { datatype = 'string', },
P286 = {
preset = 'list',
},
P296 = {
formatter = 'http://osm.sbin.ru/esr/esr:$1',
},
P301 = {
rawArticle = true,
},
P344 = {
preset = 'list',
},
P345 = {
preset = 'link',
},
P348 = {
preset = 'list',
['property-module'] = 'Wikidata/Software',
['property-function'] = 'formatVersionProperty',
},
P361 = { datatype = 'wikibase-item', },
P373 = {
datatype = 'string',
['value-module'] = 'Wikidata/media',
['value-function'] = 'formatCommonsCategory',
limit = 1,
references = false,
},
P374 = { datatype = 'external-id', },
P395 = { datatype = 'string', },
P407 = { datatype = 'wikibase-item', },
P410 = { datatype = 'wikibase-item', },
P412 = {
datatype = 'wikibase-item',
category = 'P910',
},
P413 = {
datatype = 'wikibase-item',
['claim-module'] = 'Wikidata/item',
['claim-function'] = 'formatEntityWithGenderClaim',
conjunction = ', ',
category = 'P910',
},
P414 = {
['claim-module'] = 'Wikidata/item',
['claim-function'] = 'applyDefaultTemplate',
},
P421 = { datatype = 'wikibase-item', },
P473 = { datatype = 'string', },
P495 = {
preset = 'country',
},
P505 = {
preset = 'list',
},
P512 = {
datatype = 'wikibase-item',
['property-module'] = 'Wikidata/P512',
['property-function'] = 'formatAcademicDegree',
},
P527 = {
preset = 'list',
},
P528 = {
references = false,
qualifier = 'P972',
},
P551 = {
preset = 'place',
},
P569 = {
datatype = 'time',
['claim-module'] = 'Wikidata/date',
['claim-function'] = 'formatDateOfBirthClaim',
},
P570 = {
datatype = 'time',
['claim-module'] = 'Wikidata/date',
['claim-function'] = 'formatDateOfDeathClaim',
},
P571 = { datatype = 'time', },
P576 = { datatype = 'time', },
P598 = { datatype = 'wikibase-item', },
P607 = {
datatype = 'wikibase-item',
preset = 'list',
},
P625 = { datatype = 'globe-coordinate', },
P669 = {
qualifier = 'P670',
},
P685 = {
formatter = 'https://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id=$1',
},
P721 = {
preset = 'link',
},
P764 = {
preset = 'link',
},
P803 = { datatype = 'wikibase-item', },
P856 = { datatype = 'url', },
P881 = {
novalue = 'нет',
category = 'P910',
},
P884 = {
preset = 'link',
},
P915 = {
category = 'P1740',
},
P957 = {
preset = 'link',
},
P972 = {
preset = 'catonly',
},
P1077 = {
preset = 'link',
},
P1082 = {
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P1098 = {
preset = 'quantity (date)',
unit = 'чел.',
},
P1120 = {
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P1128 = {
datatype = 'quantity',
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P1114 = {
datatype = 'quantity',
qualifier = 'P585',
},
P1174 = {
preset = 'quantity (date)',
unit = 'чел.',
},
P1195 = {
['value-module'] = 'Wikidata/Software',
['value-function'] = 'formatExtension',
conjunction = ' или ',
},
P1215 = {
datatype = 'quantity',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatVisualMagnitude'
},
P1246 = {
preset = 'link',
},
P1249 = { datatype = 'time', },
P1352 = { preset = 'quantity (date)', },
P1376 = { datatype = 'wikibase-item', },
P1402 = {
preset = 'link',
},
P1448 = {
preset = 'name',
},
P1458 = {
datatype = 'quantity',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatColorIndex'
},
P1464 = { datatype = 'wikibase-item', },
P1476 = {
preset = 'name',
},
P1477 = {
preset = 'name',
},
P1532 = {
preset = 'country',
rank = '[rank:normal, rank:preferred]',
},
P1543 = {
datatype = 'commonsMedia',
},
P1559 = {
preset = 'name',
},
P1603 = {
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P1621 = {
size = '300x300px',
},
P1692 = {
preset = 'link',
},
P1705 = {
preset = 'name',
},
P1753 = {
rowArticle = true,
},
P1809 = {
preset = 'list',
},
P1846 = {
datatype = 'commonsMedia',
fixdouble = true,
},
P2031 = {
preset = 'from-to',
to = 'P2032',
within = 'P570',
},
P2043 = {
preset = 'quantity (date)',
},
P2044 = { datatype = 'quantity', },
P2046 = {
preset = 'quantity (date)',
siConversion = false,
},
P2047 = {
siConversion = false,
},
P2048 = {
conjunction = ' или ',
},
P2060 = {
siConversion = false,
},
P2097 = {
siConversion = false,
},
P2120 = {
siConversion = false,
},
P2137 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2139 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2146 = {
siConversion = false,
},
P2214 = {
siConversion = false
},
P2226 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2257 = {
siConversion = false
},
P2260 = {
siConversion = false
},
P2295 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2324 = {
datatype = 'quantity',
preset = 'quantity (date)',
unit = 'чел.'
},
P2403 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P2425 = {
alt = 'Изображение орденской планки',
},
P2583 = {
siConversion = false,
},
P2597 = {
preset = 'catonly',
},
P2650 = { datatype = 'wikibase-item', },
P2789 = {
preset = 'list',
},
P2896 = {
siConversion = false,
},
P2910 = {
size = '100x80px',
},
P3083 = {
formatter = 'http://simbad.u-strasbg.fr/simbad/sim-id?Ident=$1',
},
P3086 = {
siConversion = false,
},
P3362 = {
preset = 'quantity (date)',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator',
countByThousands = true,
},
P4614 = {
category = 'P1200',
},
P5348 = {
siConversion = false,
},
P6257 = {
['value-module'] = 'Wikidata/number',
['value-function'] = 'formatRA',
},
P6258 = {
['value-module'] = 'Wikidata/number',
['value-function'] = 'formatDMS',
},
P6259 = {
['references'] = false,
},
P7584 = {
siConversion = false,
},
P8010 = {
datatype = 'quantity',
preset = 'quantity (date)',
unit = 'чел.',
['property-module'] = 'Wikidata/number',
['property-function'] = 'formatPropertyWithMostRecentClaimAndIndicator'
},
P8224 = {
alt = 'Изображение молекулярной модели',
},
},
categories = {
['links-to-entities-with-missing-label'] = 'Википедия:Статьи со ссылками на элементы Викиданных без подписи',
['links-to-entities-with-wikibase-error'] = 'Википедия:Страницы с ошибками скриптов, использующих Викиданные',
['links-to-entities-with-missing-local-language-label'] = 'Википедия:Статьи со ссылками на элементы Викиданных без русской подписи',
['media-contains-local-caption'] = 'Википедия:Локальная подпись у изображения из Викиданных',
['media-contains-markup'] = 'Википедия:Статьи с вики-разметкой в изображении карточки',
['media-contains-local-double'] = 'Википедия:Изображение в статье дублирует изображение в карточке',
['value-contains-table'] = 'Википедия:Статьи с табличной вставкой в карточке',
},
errors = {
['property-param-not-provided'] = 'Не дан параметр свойства',
['entity-not-found'] = 'Сущность не найдена.',
['unknown-claim-type'] = 'Неизвестный тип заявления.',
['unknown-snak-type'] = 'Неизвестный тип снэка.',
['unknown-datavalue-type'] = 'Неизвестный тип значения данных.',
['unknown-entity-type'] = 'Неизвестный тип сущности.',
['unknown-property-module'] = 'Вы должны установить и property-module, и property-function.',
['unknown-claim-module'] = 'Вы должны установить и claim-module, и claim-function.',
['unknown-value-module'] = 'Вы должны установить и value-module, и value-function.',
['property-module-not-found'] = 'Модуль для отображения свойства не найден',
['property-function-not-found'] = 'Функция для отображения свойства не найдена',
['claim-module-not-found'] = 'Модуль для отображения утверждения не найден.',
['claim-function-not-found'] = 'Функция для отображения утверждения не найдена.',
['value-module-not-found'] = 'Модуль для отображения значения не найден.',
['value-function-not-found'] = 'Функция для отображения значения не найдена.',
},
i18n = {
somevalue = "''неизвестно''",
novalue = '',
-- Обстоятельства источника
Q5727902 = 'около ',
Q18122778 = '<span style="border-bottom: 1px dotted; cursor: help;" title="предположительно">предп.</span> ',
Q30230067 = 'возможно ',
Q52834024 = '<span style="border-bottom: 1px dotted; cursor: help;" title="менее чем"><</span> ',
Q54418095 = '<span style="border-bottom: 1px dotted; cursor: help;" title="более чем">></span> ',
Q60070514 = 'примерно ',
thousandPowers = {'', ' тыс.', ' млн', ' млрд', ' трлн'},
},
deprecatedSources = {
Q355 = true, -- Facebook
Q36578 = true, -- Gemeinsame Normdatei
Q63056 = true, -- Find a Grave
Q212256 = true, -- АиФ
Q504063 = true, -- Discogs
Q523660 = true, -- International Music Score Library Project by https://ru.wikipedia.org/?diff=107090748
Q1798125 = true, -- LIBRIS
Q2621214 = true, -- Geni
Q15222191 = true, -- BNF
Q15241312 = true, -- Freebase
Q19938912 = true, -- BNF
Q21697707 = true, -- Хайазг
Q25328680 = true, -- Prabook
Q29861311 = true, -- SNAC
Q86999151 = true, -- WeChangEd
},
};
bd6091486f675bebf109cb52de53a162b05a5243
Модуль:Wikidata/Interproject
828
57
111
2025-01-02T18:27:53Z
wikipedia:ru>MBH
0
запрос Каганера
Scribunto
text/plain
local p = {}
function p.getWikivoyageLink( context )
return p.getSisterProjectLink( 'voy', 'wikivoyage', context )
end
function p.getWikibooksLink( context )
return p.getSisterProjectLink( 'b', 'wikibooks', context )
end
function p.getWikiquoteLink( context )
return p.getSisterProjectLink( 'q', 'wikiquote', context )
end
function p.getWikisourceLink( context )
return p.getSisterProjectLink( 's', 'wikisource', context )
end
function p.getWikipediaLink( context )
return p.getSisterProjectLink( 'w', 'wiki', context )
end
function p.getWiktionaryLink( context )
return p.getSisterProjectLink( 'wikt', 'wiktionary', context )
end
function p.getSisterProjectLink( projectInterwikiPrefix, projectName, context )
-- проброс параметра from откуда угодно
local entityId = nil
local p_context = context
while p_context do
if p_context.args and p_context.args.from and p_context.args.from ~= '' then
if p_context.args.from == '-' then
return ''
end
entityId = p_context.args.from
else
entityId = mw.wikibase.getEntityIdForCurrentPage()
end
p_context = p_context:getParent()
end
-- По умолчанию старается достать ссылку на русском, иначе - на родном (P103)
local wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId, 'ru' .. projectName )
if wbStatus and sitelink then
return projectInterwikiPrefix .. ':' .. sitelink
end
local wbStatus, langClaims = pcall( mw.wikibase.getBestStatements, entityId, 'P103' )
if wbStatus ~= true or not langClaims then
return ''
end
local codes = mw.loadData( 'Module:Wikidata:Dictionary/P424' )
for _, claim in ipairs( langClaims ) do
if claim.mainsnak and
claim.mainsnak.datavalue and
claim.mainsnak.datavalue.value and
claim.mainsnak.datavalue.value.id
then
local codesById = codes[ claim.mainsnak.datavalue.value.id ]
if codesById then
for _, code in ipairs( codesById ) do
wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId, code .. projectName )
if wbStatus and sitelink then
return projectInterwikiPrefix .. ':' .. code .. ':' .. sitelink
end
end
end
end
end
return ''
end
return p
48f3bdd682abd29718705f19e0411be2db6490cd
Шаблон:Doc
10
82
161
2025-01-07T17:31:17Z
wikipedia:ru>Stjn
0
не проверять страницы в основном пространстве на существование
wikitext
text/x-wiki
<includeonly>{{doc/begin|{{SUBJECTSPACE}}:{{PAGENAME:{{{1|{{SUBJECTPAGENAME}}/doc}}}}}}}
{{#if: {{{1|}}}
| {{#ifexist: {{#if: {{NAMESPACE:{{{1}}}}} | {{{1}}} | {{SUBJECTSPACE}}:{{{1}}} }}
| {{{{{1}}}|{{{2|}}}|{{{3|}}}|{{{4|}}}|{{{5|}}}}}
| {{#ifexist: {{SUBJECTSPACE}}:{{{1}}}
| {{{{{1}}}|{{{2|}}}|{{{3|}}}|{{{4|}}}|{{{5|}}}}}
| {{Документировать|{{{1}}}}}
}}
}}
| {{#ifexist: {{SUBJECTPAGENAME}}/doc
| {{{{SUBJECTPAGENAME}}/doc}}
| {{Документировать|{{SUBJECTPAGENAME}}/doc}}
}}
}}
{{doc/end}}</includeonly><noinclude>
{{doc}}
</noinclude>
7298506ab2882f16fe7a52e0e080b2780b237bb9
Заглавная страница
0
1
1
2025-01-25T17:22:37Z
MediaWiki default
1
Создать главную страницу
wikitext
text/x-wiki
__NOTOC__
== Добро пожаловать в {{SITENAME}}! ==
Эта главная страница была создана автоматически и, похоже, ещё не заменена.
=== Для бюрократа(-ов) этой вики ===
Здравствуйте и добро пожаловать на вашу новую вики! Благодарим Вас за выбор Miraheze в качестве хостинга, и мы надеемся, что вы будете пользоваться нашими услугами.
Вы можете сразу же начать работать над вашем вики-сайтов, как только пожелаете.
Нужна помощь? Нет проблем! Мы поможем вам с вашей вики по мере необходимости. Для того, чтобы начать, мы добавили несколько ссылок о работе с MediaWiki:
* [[mw:Special:MyLanguage/Help:Contents|Обсуждение руководства MediaWiki (например, навигация, редактирование, удаление страниц, блокирование пользователей)]]
* [[meta:Special:MyLanguage/FAQ|ЧЗВ по Miraheze]]
* [[meta:Special:MyLanguage/Request features|Запрос изменений настроек вашей вики.]] (Изменения расширений, оформления и логотипа/фавикона должны выполняться через [[Special:ManageWiki]] в вашей вики, см. [[meta:Special:MyLanguage/ManageWiki|ManageWiki]] для получения дополнительной информации.)
==== Но, Miraheze, я всё ещё не понимаю X! ====
Что ж, это не проблема. Даже если что-то не описано в документации/ЧЗВ, мы всё равно будем рады помочь вам. Вы можете найти нас здесь:
* [[meta:Special:MyLanguage/Help center|На нашем собственном Miraheze вики]]
* На [[phorge:|Phorge]]
* На нашем [https://miraheze.org/discord Discord-сервере]
* На IRC в #miraheze в irc.libera.chat (irc.libera.chat ([irc://irc.libera.chat/%23miraheze direct link]; [https://web.libera.chat/?channel=#miraheze вебчат]))
=== Для посетителя этой вики ===
Здравствуйте, заглавная страница по умолчанию ещё не была заменена бюрократом(-ами) этой вики. Возможно, администрация этого сайта разрабатывает эту страницу, поэтому мы рекомендуем вам зайти чуть позже.
da708791005da529f6c1fffe139a9b3660d023e2
2
1
2025-01-25T19:12:51Z
Vallenland
2
wikitext
text/x-wiki
__NOTOC__
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center;"><big>'''Добро пожаловать на Валленланд Вики, энциклопедию о микрогосударстве Валленланд.'''</big>
Валленланд - микрогосударство на части территории города Пскова одноимённой области в России. Оно было основано в 2025 году и активно развивается.
</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Статьи, которые следует прочитать...'''
[[Справка:Что такое Валленланд|Простым людям]]ㅤㅤ [[Справка:Как доказать гражданство для вики|Гражданам Валленланда]]ㅤㅤ [[Справка:Установка дипломатических отношений|Главам микронаций]]
[[Справка:Как получить гражданство|Желающим получить гражданство Валленланда]]</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Избранная статья'''
Тут ее пока нету но скоро будет
</div>
0135b05ca03063d50cf606bc46df5da4cb862321
3
2
2025-01-25T19:13:33Z
Vallenland
2
Защитил страницу [[Заглавная страница]] ([Редактирование=Разрешено только администраторам] (бессрочно) [Переименование=Разрешено только администраторам] (бессрочно))
wikitext
text/x-wiki
__NOTOC__
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center;"><big>'''Добро пожаловать на Валленланд Вики, энциклопедию о микрогосударстве Валленланд.'''</big>
Валленланд - микрогосударство на части территории города Пскова одноимённой области в России. Оно было основано в 2025 году и активно развивается.
</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Статьи, которые следует прочитать...'''
[[Справка:Что такое Валленланд|Простым людям]]ㅤㅤ [[Справка:Как доказать гражданство для вики|Гражданам Валленланда]]ㅤㅤ [[Справка:Установка дипломатических отношений|Главам микронаций]]
[[Справка:Как получить гражданство|Желающим получить гражданство Валленланда]]</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Избранная статья'''
Тут ее пока нету но скоро будет
</div>
0135b05ca03063d50cf606bc46df5da4cb862321
6
3
2025-01-25T20:02:14Z
Vallenland
2
wikitext
text/x-wiki
__NOTOC__
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center;">[[Файл:Vallenbox (greeting).png|центр|безрамки|160x160пкс]]<big>'''Добро пожаловать на Валленланд Вики, энциклопедию о микрогосударстве Валленланд.'''</big>
Валленланд - микрогосударство на части территории города Пскова одноимённой области в России. Оно было основано в 2025 году и активно развивается.
</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Статьи, которые следует прочитать...'''
[[Справка:Что такое Валленланд|Простым людям]]ㅤㅤ [[Справка:Как доказать гражданство для вики|Гражданам Валленланда]]ㅤㅤ [[Справка:Установка дипломатических отношений|Главам микронаций]]
[[Справка:Как получить гражданство|Желающим получить гражданство Валленланда]]</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Избранная статья'''
Тут ее пока нету но скоро будет
</div>
bf55e9be9033796f318da1a5196edb3104182477
Шаблон:Цвет/Композитор.css
10
91
179
2025-01-25T19:46:07Z
wikipedia:ru>Putnik
0
упрощение селекторов
text
text/plain
.infobox-above,
.infobox-header,
.infobox-below {
background: #bfe0bf;
}
@media screen {
html.skin-theme-clientpref-night .infobox-above,
html.skin-theme-clientpref-night .infobox-header {
background: #224422;
}
html.skin-theme-clientpref-night .infobox-below {
background: #182f18;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox-above,
html.skin-theme-clientpref-os .infobox-header {
background: #224422;
}
html.skin-theme-clientpref-os .infobox-below {
background: #182f18;
}
}
/*
[[Категория:Шаблоны:Подстраницы CSS]]
[[Категория:Шаблоны:Цвета по темам:Музыка|Композитор.css]]
*/
174fb6f61c3dc1ef339cd4b496da585e1c4195d6
Файл:Logo.png
6
2
4
2025-01-25T19:56:21Z
Vallenland
2
wikitext
text/x-wiki
x
11f6ad8ec52a2984abaafd7c3b516503785c2072
Файл:Vallenbox (greeting).png
6
3
5
2025-01-25T20:01:43Z
Vallenland
2
wikitext
text/x-wiki
gg
f3226f91f77a87d909b8920adc91f9a301a7316b
Валленланд
0
4
7
2025-01-25T20:34:38Z
Vallenland
2
начало
wikitext
text/x-wiki
'''Валленланд''' (официально '''Валленландская Севастократия''', допускается также написание '''Валенланд''' и '''Валенландская Севастократия''') - микрогосударство на части зелёной территории города Пскова Псковской области. Официально [[Международное признание Валленланда|признан]] макрогосударствами как территория, принадлежащая Российской Федерации. Территории Валленланда расположены к востоку от 4-го многопрофильного лицея города Пскова. Они периодически контролируются то Валленлендом, то Россией. Площадь этих территорий, по измерениям Google Maps, составляет 4060 м<small><sup>2</sup></small> (0,406 га).
Непостоянное [[Население Валленланда|население]] Валленланда составляет 1 человека, который и является правителем данного микрогосударства. По национальности он - цыган, следовательно, 100% населения Валленланда составляют цыгане. [[Мандат о независимости Валленланда|Мандатом о независимости]] от [[Национальный день принятия мандата о независимости Валленланда|22 января 2025 года]] установлены также полностью открытые границы и отсутствие государственного контроля за ними. В связи с этим через территорию Валленланда (чаще всего транзитом) проходят несколько десятков человек в день.
Главный город, равно как и административно-территориальное устройство, у Валленландской Севастократии отсутствует в связи со слишком маленькой площадью для необходимости этого. Из-за этого Валленланд можно отнести к сверхунитарным микрогосударствам.
Валленланд имеет всего лишь одну общую границу с Российской Федерацией длиной в 453 м. Денежной единицы в силу временной нецелесообразности её введения (слишком малое число граждан) Валленланд не имеет. В противном случае денежной единицей станет российский рубль.
Валленландская Севастократия долго находилась под властью многих государств - от Киевской Руси до Российской Федерации. Полный перечень всех стран, которые включали её в свой состав: Киевская Русь, Новгородская Республика, Псковская земля (позже - фактически под властью России), Русское государство, Российская империя, Эстония, Российская Советская Федеративная Социалистическая Республика, Великогерманский Рейх, вновь РСФСР и Российская Федерация. Независимый Валленланд появился 22 января 2025 года.
Во главе Валленланда стоит севастократор (до этого севастократор был высшим придворным титулом Византии, тем не менее, примерно соответствующим королю), имеющий абсолютную власть в стране до тех пор, пока не будет написана и принята первая конституция Валленланда. На 2025 год этот титул принадлежит Макару Григорьеву.
8415c00debfc340614c6082b870bc7364f0e2f52
MediaWiki:Common.css
8
5
8
2025-01-25T20:37:59Z
Vallenland
2
Новая страница: «/* Размещённый здесь CSS будет применяться ко всем темам оформления */ .infobox { background: #eee; border: 1px solid #aaa; float: right; margin: 0 0 1em 1em; padding: 1em; width: 400px; } .infobox-title { font-size: 2em; text-align: center; } .infobox-image { text-align: center; } .infobox-table th { text-align: right; vertical-align: top; width: 120px; } .i...»
css
text/css
/* Размещённый здесь CSS будет применяться ко всем темам оформления */
.infobox {
background: #eee;
border: 1px solid #aaa;
float: right;
margin: 0 0 1em 1em;
padding: 1em;
width: 400px;
}
.infobox-title {
font-size: 2em;
text-align: center;
}
.infobox-image {
text-align: center;
}
.infobox-table th {
text-align: right;
vertical-align: top;
width: 120px;
}
.infobox-table td {
vertical-align: top;
}
2bea267ce64b9c1108105f9be0cb220b40436b08
Шаблон:Langi
10
7
12
11
2025-01-25T21:00:05Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<span lang="{{{1}}}" xml:lang="{{{1}}}" style="font-style:italic;">{{{2}}}</span><noinclude>{{doc}}</noinclude>
7bb9f9098c88e770b982402adf30a3bbf645aa4b
Модуль:Arguments
828
8
14
13
2025-01-25T21:00:05Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- This module provides easy processing of arguments passed to Scribunto from
-- #invoke. It is intended for use by other Lua modules, and should not be
-- called from #invoke directly.
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local arguments = {}
-- Generate four different tidyVal functions, so that we don't have to check the
-- options every time we call it.
local function tidyValDefault(key, val)
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val == '' then
return nil
else
return val
end
else
return val
end
end
local function tidyValTrimOnly(key, val)
if type(val) == 'string' then
return val:match('^%s*(.-)%s*$')
else
return val
end
end
local function tidyValRemoveBlanksOnly(key, val)
if type(val) == 'string' then
if val:find('%S') then
return val
else
return nil
end
else
return val
end
end
local function tidyValNoChange(key, val)
return val
end
local function matchesTitle(given, title)
local tp = type( given )
return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title
end
local translate_mt = { __index = function(t, k) return k end }
function arguments.getArgs(frame, options)
checkType('getArgs', 1, frame, 'table', true)
checkType('getArgs', 2, options, 'table', true)
frame = frame or {}
options = options or {}
--[[
-- Set up argument translation.
--]]
options.translate = options.translate or {}
if getmetatable(options.translate) == nil then
setmetatable(options.translate, translate_mt)
end
if options.backtranslate == nil then
options.backtranslate = {}
for k,v in pairs(options.translate) do
options.backtranslate[v] = k
end
end
if options.backtranslate and getmetatable(options.backtranslate) == nil then
setmetatable(options.backtranslate, {
__index = function(t, k)
if options.translate[k] ~= k then
return nil
else
return k
end
end
})
end
--[[
-- Get the argument tables. If we were passed a valid frame object, get the
-- frame arguments (fargs) and the parent frame arguments (pargs), depending
-- on the options set and on the parent frame's availability. If we weren't
-- passed a valid frame object, we are being called from another Lua module
-- or from the debug console, so assume that we were passed a table of args
-- directly, and assign it to a new variable (luaArgs).
--]]
local fargs, pargs, luaArgs
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then
if options.wrappers then
--[[
-- The wrappers option makes Module:Arguments look up arguments in
-- either the frame argument table or the parent argument table, but
-- not both. This means that users can use either the #invoke syntax
-- or a wrapper template without the loss of performance associated
-- with looking arguments up in both the frame and the parent frame.
-- Module:Arguments will look up arguments in the parent frame
-- if it finds the parent frame's title in options.wrapper;
-- otherwise it will look up arguments in the frame object passed
-- to getArgs.
--]]
local parent = frame:getParent()
if not parent then
fargs = frame.args
else
local title = parent:getTitle():gsub('/песочница$', '')
local found = false
if matchesTitle(options.wrappers, title) then
found = true
elseif type(options.wrappers) == 'table' then
for _,v in pairs(options.wrappers) do
if matchesTitle(v, title) then
found = true
break
end
end
end
-- We test for false specifically here so that nil (the default) acts like true.
if found or options.frameOnly == false then
pargs = parent.args
end
if not found or options.parentOnly == false then
fargs = frame.args
end
end
else
-- options.wrapper isn't set, so check the other options.
if not options.parentOnly then
fargs = frame.args
end
if not options.frameOnly then
local parent = frame:getParent()
pargs = parent and parent.args or nil
end
end
if options.parentFirst then
fargs, pargs = pargs, fargs
end
else
luaArgs = frame
end
-- Set the order of precedence of the argument tables. If the variables are
-- nil, nothing will be added to the table, which is how we avoid clashes
-- between the frame/parent args and the Lua args.
local argTables = {fargs}
argTables[#argTables + 1] = pargs
argTables[#argTables + 1] = luaArgs
--[[
-- Generate the tidyVal function. If it has been specified by the user, we
-- use that; if not, we choose one of four functions depending on the
-- options chosen. This is so that we don't have to call the options table
-- every time the function is called.
--]]
local tidyVal = options.valueFunc
if tidyVal then
if type(tidyVal) ~= 'function' then
error(
"bad value assigned to option 'valueFunc'"
.. '(function expected, got '
.. type(tidyVal)
.. ')',
2
)
end
elseif options.trim ~= false then
if options.removeBlanks ~= false then
tidyVal = tidyValDefault
else
tidyVal = tidyValTrimOnly
end
else
if options.removeBlanks ~= false then
tidyVal = tidyValRemoveBlanksOnly
else
tidyVal = tidyValNoChange
end
end
--[[
-- Set up the args, metaArgs and nilArgs tables. args will be the one
-- accessed from functions, and metaArgs will hold the actual arguments. Nil
-- arguments are memoized in nilArgs, and the metatable connects all of them
-- together.
--]]
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}
setmetatable(args, metatable)
local function mergeArgs(tables)
--[[
-- Accepts multiple tables as input and merges their keys and values
-- into one table. If a value is already present it is not overwritten;
-- tables listed earlier have precedence. We are also memoizing nil
-- values, which can be overwritten if they are 's' (soft).
--]]
for _, t in ipairs(tables) do
for key, val in pairs(t) do
if metaArgs[key] == nil and nilArgs[key] ~= 'h' then
local tidiedVal = tidyVal(key, val)
if tidiedVal == nil then
nilArgs[key] = 's'
else
metaArgs[key] = tidiedVal
end
end
end
end
end
--[[
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,
-- and are only fetched from the argument tables once. Fetching arguments
-- from the argument tables is the most resource-intensive step in this
-- module, so we try and avoid it where possible. For this reason, nil
-- arguments are also memoized, in the nilArgs table. Also, we keep a record
-- in the metatable of when pairs and ipairs have been called, so we do not
-- run pairs and ipairs on the argument tables more than once. We also do
-- not run ipairs on fargs and pargs if pairs has already been run, as all
-- the arguments will already have been copied over.
--]]
metatable.__index = function (t, key)
--[[
-- Fetches an argument when the args table is indexed. First we check
-- to see if the value is memoized, and if not we try and fetch it from
-- the argument tables. When we check memoization, we need to check
-- metaArgs before nilArgs, as both can be non-nil at the same time.
-- If the argument is not present in metaArgs, we also check whether
-- pairs has been run yet. If pairs has already been run, we return nil.
-- This is because all the arguments will have already been copied into
-- metaArgs by the mergeArgs function, meaning that any other arguments
-- must be nil.
--]]
if type(key) == 'string' then
key = options.translate[key]
end
local val = metaArgs[key]
if val ~= nil then
return val
elseif metatable.donePairs or nilArgs[key] then
return nil
end
for _, argTable in ipairs(argTables) do
local argTableVal = tidyVal(key, argTable[key])
if argTableVal ~= nil then
metaArgs[key] = argTableVal
return argTableVal
end
end
nilArgs[key] = 'h'
return nil
end
metatable.__newindex = function (t, key, val)
-- This function is called when a module tries to add a new value to the
-- args table, or tries to change an existing value.
if type(key) == 'string' then
key = options.translate[key]
end
if options.readOnly then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; the table is read-only',
2
)
elseif options.noOverwrite and args[key] ~= nil then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; overwriting existing arguments is not permitted',
2
)
elseif val == nil then
--[[
-- If the argument is to be overwritten with nil, we need to erase
-- the value in metaArgs, so that __index, __pairs and __ipairs do
-- not use a previous existing value, if present; and we also need
-- to memoize the nil in nilArgs, so that the value isn't looked
-- up in the argument tables if it is accessed again.
--]]
metaArgs[key] = nil
nilArgs[key] = 'h'
else
metaArgs[key] = val
end
end
local function translatenext(invariant)
local k, v = next(invariant.t, invariant.k)
invariant.k = k
if k == nil then
return nil
elseif type(k) ~= 'string' or not options.backtranslate then
return k, v
else
local backtranslate = options.backtranslate[k]
if backtranslate == nil then
-- Skip this one. This is a tail call, so this won't cause stack overflow
return translatenext(invariant)
else
return backtranslate, v
end
end
end
metatable.__pairs = function ()
-- Called when pairs is run on the args table.
if not metatable.donePairs then
mergeArgs(argTables)
metatable.donePairs = true
end
return translatenext, { t = metaArgs }
end
local function inext(t, i)
-- This uses our __index metamethod
local v = t[i + 1]
if v ~= nil then
return i + 1, v
end
end
metatable.__ipairs = function (t)
-- Called when ipairs is run on the args table.
return inext, t, 0
end
return args
end
return arguments
e6be8dfccffa2057c3d50700f350d8d140c1dbf9
Модуль:Check for unknown parameters
828
9
16
15
2025-01-25T21:00:06Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- This module may be used to compare the arguments passed to the parent
-- with a list of arguments, returning a specified result if an argument is
-- not on the list
local p = {}
local function trim(s)
return s:match('^%s*(.-)%s*$')
end
local function isnotempty(s)
return s and trim(s) ~= ''
end
function p.check (frame)
local args = frame.args
local pargs = frame:getParent().args
local ignoreblank = isnotempty(frame.args['ignoreblank'])
local showblankpos = isnotempty(frame.args['showblankpositional'])
local knownargs = {}
local unknown = frame.args['unknown'] or 'Found _VALUE_, '
local preview = frame.args['preview']
local values = {}
local res = {}
local regexps = {}
-- create the list of known args, regular expressions, and the return string
for k, v in pairs(args) do
if type(k) == 'number' then
v = trim(v)
knownargs[v] = 1
elseif k:find('^regexp[1-9][0-9]*$') then
table.insert(regexps, '^' .. v .. '$')
end
end
if isnotempty(preview) then
preview = '<div class="hatnote" style="color: var(--color-error, #d73333)"><strong>Предупреждение:</strong> '
.. preview
.. ' (это сообщение видно только при предпросмотре страницы).</div>'
elseif preview == nil then
preview = unknown
end
-- loop over the parent args, and make sure they are on the list
for k, v in pairs(pargs) do
if type(k) == 'string' and knownargs[k] == nil then
local knownflag = false
for i, regexp in ipairs(regexps) do
if mw.ustring.match(k, regexp) then
knownflag = true
break
end
end
if not knownflag and ( not ignoreblank or isnotempty(v) ) then
k = mw.ustring.gsub(k, '[^%w\-_ ]', '?')
table.insert(values, k)
end
elseif type(k) == 'number' and
knownargs[tostring(k)] == nil and
( showblankpos or isnotempty(v) )
then
local vlen = mw.ustring.len(v)
v = mw.ustring.sub(v, 1, (vlen < 25) and vlen or 25)
v = mw.ustring.gsub(v, '[^%w\-_ ]', '?')
table.insert(values, k .. ' = ' .. v .. ((vlen >= 25) and ' ...' or ''))
end
end
-- add resuls to the output tables
if #values > 0 then
if frame:preprocess( "{{REVISIONID}}" ) == "" then
unknown = preview
end
for k, v in pairs(values) do
if v == '' then
-- Fix odd bug for | = which gets stripped to the empty string and
-- breaks category links
v = ' '
end
local r = unknown:gsub('_VALUE_', v)
table.insert(res, r)
end
end
return table.concat(res)
end
function p.generate (frame)
local res = '{{#invoke:check for unknown parameters|check\n' ..
'|unknown=' .. frame.args['unknown'] .. '\n'
local checkerparams = {'ignoreblank', 'preview', 'showblankpositional'}
for _, v in pairs(checkerparams) do
if frame.args[v] then
res = res .. '|' .. v .. '=' .. frame.args[v] .. '\n'
end
end
local templatenamespace = frame.args[1]
local templatetitle = frame.args[2]
local pagepointer = mw.title.new(templatetitle, templatenamespace) -- именно такой порядок!
local text = pagepointer.getContent(pagepointer)
local params = {}
for param in string.gmatch(text, '\{\{\{([^\|\}]*)') do
params[#params+1] = mw.text.trim(param)
end
table.sort(params)
for k, v in pairs(params) do
if k == 1 or v ~= params[k-1] then
res = res .. '|' .. v
end
end
res = res .. '}}'
return res
end
return p
9da4c0ae23797bb024279d7544e897ae3f2bbf43
Модуль:TableTools
828
10
18
17
2025-01-25T21:00:06Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--[[
------------------------------------------------------------------------------------
-- TableTools --
-- --
-- This module includes a number of functions for dealing with Lua tables. --
-- It is a meta-module, meant to be called from other Lua modules, and should --
-- not be called directly from #invoke. --
------------------------------------------------------------------------------------
--]]
local libraryUtil = require('libraryUtil')
local p = {}
-- Define often-used variables and functions.
local floor = math.floor
local infinity = math.huge
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
--[[
------------------------------------------------------------------------------------
-- isPositiveInteger
--
-- This function returns true if the given value is a positive integer, and false
-- if not. Although it doesn't operate on tables, it is included here as it is
-- useful for determining whether a given table key is in the array part or the
-- hash part of a table.
------------------------------------------------------------------------------------
--]]
function p.isPositiveInteger(v)
if type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity then
return true
else
return false
end
end
--[[
------------------------------------------------------------------------------------
-- isNan
--
-- This function returns true if the given number is a NaN value, and false
-- if not. Although it doesn't operate on tables, it is included here as it is
-- useful for determining whether a value can be a valid table key. Lua will
-- generate an error if a NaN is used as a table key.
------------------------------------------------------------------------------------
--]]
function p.isNan(v)
if type(v) == 'number' and tostring(v) == '-nan' then
return true
else
return false
end
end
--[[
------------------------------------------------------------------------------------
-- shallowClone
--
-- This returns a clone of a table. The value returned is a new table, but all
-- subtables and functions are shared. Metamethods are respected, but the returned
-- table will have no metatable of its own.
------------------------------------------------------------------------------------
--]]
function p.shallowClone(t)
local ret = {}
for k, v in pairs(t) do
ret[k] = v
end
return ret
end
--[[
------------------------------------------------------------------------------------
-- removeDuplicates
--
-- This removes duplicate values from an array. Non-positive-integer keys are
-- ignored. The earliest value is kept, and all subsequent duplicate values are
-- removed, but otherwise the array order is unchanged.
------------------------------------------------------------------------------------
--]]
function p.removeDuplicates(t)
checkType('removeDuplicates', 1, t, 'table')
local isNan = p.isNan
local ret, exists = {}, {}
for i, v in ipairs(t) do
if isNan(v) then
-- NaNs can't be table keys, and they are also unique, so we don't need to check existence.
ret[#ret + 1] = v
else
if not exists[v] then
ret[#ret + 1] = v
exists[v] = true
end
end
end
return ret
end
--[[
------------------------------------------------------------------------------------
-- numKeys
--
-- This takes a table and returns an array containing the numbers of any numerical
-- keys that have non-nil values, sorted in numerical order.
------------------------------------------------------------------------------------
--]]
function p.numKeys(t)
checkType('numKeys', 1, t, 'table')
local isPositiveInteger = p.isPositiveInteger
local nums = {}
for k, v in pairs(t) do
if isPositiveInteger(k) then
nums[#nums + 1] = k
end
end
table.sort(nums)
return nums
end
--[[
------------------------------------------------------------------------------------
-- affixNums
--
-- This takes a table and returns an array containing the numbers of keys with the
-- specified prefix and suffix. For example, for the table
-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will
-- return {1, 3, 6}.
------------------------------------------------------------------------------------
--]]
function p.affixNums(t, prefix, suffix)
checkType('affixNums', 1, t, 'table')
checkType('affixNums', 2, prefix, 'string', true)
checkType('affixNums', 3, suffix, 'string', true)
local function cleanPattern(s)
-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.
s = s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
return s
end
prefix = prefix or ''
suffix = suffix or ''
prefix = cleanPattern(prefix)
suffix = cleanPattern(suffix)
local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'
local nums = {}
for k, v in pairs(t) do
if type(k) == 'string' then
local num = mw.ustring.match(k, pattern)
if num then
nums[#nums + 1] = tonumber(num)
end
end
end
table.sort(nums)
return nums
end
--[[
------------------------------------------------------------------------------------
-- numData
--
-- Given a table with keys like ("foo1", "bar1", "foo2", "baz2"), returns a table
-- of subtables in the format
-- { [1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'} }
-- Keys that don't end with an integer are stored in a subtable named "other".
-- The compress option compresses the table so that it can be iterated over with
-- ipairs.
------------------------------------------------------------------------------------
--]]
function p.numData(t, compress)
checkType('numData', 1, t, 'table')
checkType('numData', 2, compress, 'boolean', true)
local ret = {}
for k, v in pairs(t) do
local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$')
if num then
num = tonumber(num)
local subtable = ret[num] or {}
if prefix == '' then
-- Positional parameters match the blank string; put them at the start of the subtable instead.
prefix = 1
end
subtable[prefix] = v
ret[num] = subtable
else
local subtable = ret.other or {}
subtable[k] = v
ret.other = subtable
end
end
if compress then
local other = ret.other
ret = p.compressSparseArray(ret)
ret.other = other
end
return ret
end
--[[
------------------------------------------------------------------------------------
-- compressSparseArray
--
-- This takes an array with one or more nil values, and removes the nil values
-- while preserving the order, so that the array can be safely traversed with
-- ipairs.
------------------------------------------------------------------------------------
--]]
function p.compressSparseArray(t)
checkType('compressSparseArray', 1, t, 'table')
local ret = {}
local nums = p.numKeys(t)
for _, num in ipairs(nums) do
ret[#ret + 1] = t[num]
end
return ret
end
--[[
------------------------------------------------------------------------------------
-- sparseIpairs
--
-- This is an iterator for sparse arrays. It can be used like ipairs, but can
-- handle nil values.
------------------------------------------------------------------------------------
--]]
function p.sparseIpairs(t)
checkType('sparseIpairs', 1, t, 'table')
local nums = p.numKeys(t)
local i = 0
local lim = #nums
return function ()
i = i + 1
if i <= lim then
local key = nums[i]
return key, t[key]
else
return nil, nil
end
end
end
--[[
------------------------------------------------------------------------------------
-- size
--
-- This returns the size of a key/value pair table. It will also work on arrays,
-- but for arrays it is more efficient to use the # operator.
------------------------------------------------------------------------------------
--]]
function p.size(t)
checkType('size', 1, t, 'table')
local i = 0
for k in pairs(t) do
i = i + 1
end
return i
end
local function defaultKeySort(item1, item2)
-- "number" < "string", so numbers will be sorted before strings.
local type1, type2 = type(item1), type(item2)
if type1 ~= type2 then
return type1 < type2
else -- This will fail with table, boolean, function.
return item1 < item2
end
end
--[[
Returns a list of the keys in a table, sorted using either a default
comparison function or a custom keySort function.
]]
function p.keysToList(t, keySort, checked)
if not checked then
checkType('keysToList', 1, t, 'table')
checkTypeMulti('keysToList', 2, keySort, { 'function', 'boolean', 'nil' })
end
local list = {}
local index = 1
for key, value in pairs(t) do
list[index] = key
index = index + 1
end
if keySort ~= false then
keySort = type(keySort) == 'function' and keySort or defaultKeySort
table.sort(list, keySort)
end
return list
end
--[[
Iterates through a table, with the keys sorted using the keysToList function.
If there are only numerical keys, sparseIpairs is probably more efficient.
]]
function p.sortedPairs(t, keySort)
checkType('sortedPairs', 1, t, 'table')
checkType('sortedPairs', 2, keySort, 'function', true)
local list = p.keysToList(t, keySort, true)
local i = 0
return function()
i = i + 1
local key = list[i]
if key ~= nil then
return key, t[key]
else
return nil, nil
end
end
end
--[[
Returns true if all keys in the table are consecutive integers starting at 1.
--]]
function p.isArray(t)
checkType("isArray", 1, t, "table")
local i = 0
for k, v in pairs(t) do
i = i + 1
if t[i] == nil then
return false
end
end
return true
end
-- { "a", "b", "c" } -> { a = 1, b = 2, c = 3 }
function p.invert(array)
checkType("invert", 1, array, "table")
local map = {}
for i, v in ipairs(array) do
map[v] = i
end
return map
end
--[[
{ "a", "b", "c" } -> { ["a"] = true, ["b"] = true, ["c"] = true }
--]]
function p.listToSet(t)
checkType("listToSet", 1, t, "table")
local set = {}
for _, item in ipairs(t) do
set[item] = true
end
return set
end
--[[
Recursive deep copy function.
Preserves identities of subtables.
]]
local function _deepCopy(orig, includeMetatable, already_seen)
-- Stores copies of tables indexed by the original table.
already_seen = already_seen or {}
local copy = already_seen[orig]
if copy ~= nil then
return copy
end
if type(orig) == 'table' then
copy = {}
for orig_key, orig_value in pairs(orig) do
copy[deepcopy(orig_key, includeMetatable, already_seen)] = deepcopy(orig_value, includeMetatable, already_seen)
end
already_seen[orig] = copy
if includeMetatable then
local mt = getmetatable(orig)
if mt ~= nil then
local mt_copy = deepcopy(mt, includeMetatable, already_seen)
setmetatable(copy, mt_copy)
already_seen[mt] = mt_copy
end
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
function p.deepCopy(orig, noMetatable, already_seen)
checkType("deepCopy", 3, already_seen, "table", true)
return _deepCopy(orig, not noMetatable, already_seen)
end
--[[
Concatenates all values in the table that are indexed by a number, in order.
sparseConcat{ a, nil, c, d } => "acd"
sparseConcat{ nil, b, c, d } => "bcd"
]]
function p.sparseConcat(t, sep, i, j)
local list = {}
local list_i = 0
for _, v in p.sparseIpairs(t) do
list_i = list_i + 1
list[list_i] = v
end
return table.concat(list, sep, i, j)
end
--[[
-- This returns the length of a table, or the first integer key n counting from
-- 1 such that t[n + 1] is nil. It is similar to the operator #, but may return
-- a different value when there are gaps in the array portion of the table.
-- Intended to be used on data loaded with mw.loadData. For other tables, use #.
-- Note: #frame.args in frame object always be set to 0, regardless of
-- the number of unnamed template parameters, so use this function for
-- frame.args.
--]]
function p.length(t)
local i = 1
while t[i] ~= nil do
i = i + 1
end
return i - 1
end
function p.inArray(arr, valueToFind)
checkType("inArray", 1, arr, "table")
-- if valueToFind is nil, error?
for _, v in ipairs(arr) do
if v == valueToFind then
return true
end
end
return false
end
return p
fe918509f168332267834b3a6f5c219a9de5b2e7
Модуль:Template call code
828
11
20
19
2025-01-25T21:00:07Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local getArgs = require('Module:Arguments').getArgs
local ru = mw.language.new('ru')
local p = {}
-- Используется для того, чтобы можно было удалять элементы из таблицы
local function copy(other)
local res = {}
for k, v in pairs(other) do
res[k] = v
end
return res
end
local function makeInvokeFunc(funcName, flags)
return function (frame)
local args = copy(getArgs(frame, {
trim = false,
removeBlanks = false
}))
return p[funcName](args, flags)
end
end
--предотвращает обработку вики-текста в отображении образца
local function processText(str, nowiki)
local res = str
if nowiki then
str = mw.text.unstripNoWiki(str)
str = string.gsub(str, '%[', '[')
str = string.gsub(str, '%]', ']')
str = string.gsub(str, '<', '<')
str = string.gsub(str, '>', '>')
str = string.gsub(str, '{', '{')
str = string.gsub(str, '|', '|')
str = string.gsub(str, '}', '}')
str = string.gsub(str, '\'', ''')
str = string.gsub(str, '"', '"')
str = string.gsub(str, '(://)', '<span>%1</span>')
end
return str
end
local function addParams(args, params)
local text, equals_pos, param, value = '', 0, '', ''
local function addPipe()
if params.spaced then
text = text .. ' '
end
text = text .. '<span class="'
if not params.spaced then
text = text .. ' ts-templateCallCode-pipe'
end
if not params.black then
text = text .. ' ts-templateCallCode-weak'
end
-- |, чтобы не трактовалось как разделитель ячеек в таблицах
text = text .. '">|</span>'
end
local beforeParam = '<span class="ts-templateCallCode-param">'
local afterParam = '</span>'
for k, v in pairs(args) do
if type(k) == 'number' then -- Неименованные параметры
if k >= params.from then
equals_pos = v:find('=')
if equals_pos and v:find('{{=}}') == equals_pos - 2 then
equals_pos = nil
end
if equals_pos then -- Содержащие «=» преобразуем в именованные
param = v:sub(1, equals_pos - 1)
value = v:sub(equals_pos + 1)
addPipe()
text = text .. beforeParam .. processText(param, params.nowiki) .. '=' .. processText(value, params.nowiki) .. afterParam
else -- Истинно неименованные
addPipe()
local paramValue = processText(v, params.nowiki)
if #paramValue ~= 0 then
text = text .. beforeParam .. paramValue .. afterParam
end
end
end
elseif not k:find('^_') then -- Именованные параметры, исключая модификаторы внешнего вида
addPipe()
text = text .. beforeParam .. processText(k, params.nowiki) .. '=' .. processText(v, params.nowiki) .. afterParam
end
end
return text
end
function p._main(args, flags)
local name = args[1]
table.remove(args, 1)
-- Вещи типа «=» в первом параметре
if not name then
for k, v in pairs(args) do
if not k:find('^_') then
name = k .. '=' .. v
args[k] = nil
break
end
end
end
local optpText
if not flags.withoutParams then
if name then
local spanOffset = mw.ustring.find(name, '<span') -- След использования шаблона optp
if spanOffset then
optpText = mw.ustring.sub(name, spanOffset)
name = mw.ustring.sub(name, 1, spanOffset - 1)
end
end
end
local yesno = require('Module:Yesno')
local nolink, subst, podst, global, nav, noRedirect, ucFirst, black, nobr
local tag, style, comment, lang, sister, global, textInPlaceOfName,
namePrefix, prefix, postfix, nowiki
local spaced, from
if flags.withoutParams then
for i, v in ipairs(args) do
if v == 'nl' or v == 'nolink' then
noLink = true
elseif v == 's' then
subst = true
elseif v == 'п' then
podst = true
elseif v == 'g' then
global = true
elseif v == 'nav' then
nav = true
elseif v == 'noredir' then
noRedirect = true
elseif v == 'u' then
ucFirst = true
elseif v == 'b' then
black = true
elseif v == 'nobr' then
nobr = true
end
end
tag = args.tag or 'span'
style = args.style
comment = args.comment
lang = args.lang
sister = args.sister
textInPlaceOfName = args.text
namePrefix = args.nameprefix
prefix = args.prefix
postfix = args.postfix
nowiki = args.nowiki
else
noLink = yesno(args._nolink or args._nl, false) or not yesno(args._link, false)
subst = yesno(args._s, false)
podst = yesno(args['_п'], false)
global = yesno(args._g, false)
nav = yesno(args._nav, false)
noRedirect = yesno(args._noredir, false)
ucFirst = yesno(args._u, false)
black = yesno(args._b, false)
nobr = yesno(args._nobr, false)
tag = args._tag or 'span'
style = args._style
comment = args._comment
lang = args._lang
sister = args._sister
textInPlaceOfName = args._text
namePrefix = args._nameprefix
prefix = args._prefix
postfix = args._postfix
nowiki = args._nowiki
spaced = yesno(args._spaced, false)
from = (tonumber(args._from) or 2) - 1
end
global = global or name and mw.ustring.sub(name, 1, 1) == ':'
black = black or tag ~= 'span'
if textInPlaceOfName == '' then
textInPlaceOfName = nil
end
if comment == '' then
comment = nil
end
if lang == '' then
lang = nil
end
if sister == '' then
sister = nil
end
if namePrefix == '' then
namePrefix = nil
end
if name then
local trimmedName = mw.text.trim(name)
if ru:lc(mw.ustring.sub(trimmedName, 1, 6)) == 'subst:' then
subst = true
name = mw.ustring.sub(trimmedName, 7)
end
if ru:lc(mw.ustring.sub(trimmedName, 1, 6)) == 'подст:' then
podst = true
name = mw.ustring.sub(trimmedName, 7)
end
end
if subst then
namePrefix = 'subst:'
elseif podst then
namePrefix = 'подст:'
end
local currentTitle = mw.title.getCurrentTitle()
-- При опущенном первом параметре берём имя шаблона из названия страницы
if name == '' or not name then
local currentTitleRoot = currentTitle.rootText
if not ucFirst and
(
(
ru:uc(currentTitleRoot) ~= currentTitleRoot and
-- Книга:Литературное наследство, TranslateDate
not mw.ustring.match(currentTitleRoot, '^[А-Яа-яA-Za-z]+:?[А-ЯA-Z]')
) or
#currentTitleRoot == 1
)
then
name = ru:lcfirst(currentTitleRoot)
else
name = currentTitleRoot
end
end
-- Начинаем собирать код
local linkBody, titleObject, linkBegin, linkDivider, linkEnd
local prefixes = {}
if lang then
table.insert(prefixes, lang)
end
if sister then
table.insert(prefixes, sister)
end
linkBody = table.concat(prefixes, ':')
if #linkBody ~= 0 then
linkBody = ':' .. linkBody
end
if mw.ustring.sub(name, 1, 1) ~= ':' then
linkBody = linkBody .. ':'
end
if not global then
linkBody = linkBody .. 'Template:'
end
linkBody = linkBody .. name
titleObject = mw.title.new(linkBody)
local noLink = noLink or currentTitle == titleObject
if not noLink then
if not noRedirect or (
noRedirect and
not lang and
not sister and
not titleObject.exists
) then
linkBegin = '[['
linkEnd = ']]'
linkDivider = '|'
else
linkBegin = '['
linkEnd = ']'
linkDivider = ' '
linkBody = titleObject:fullUrl('redirect=no')
end
end
local text = ''
if tag then
text = text .. '<' .. tag .. ' class="ts-templateCallCode'
if nobr then
text = text .. ' nowrap'
end
text = text .. '"'
if style then
text = text .. ' style="' .. style .. '"'
end
text = text .. '>'
end
if prefix then
text = text .. processText(prefix, nowiki)
end
text = text .. '<span class="'
if not spaced then
text = text .. ' ts-templateCallCode-opening'
end
if not black then
text = text .. ' ts-templateCallCode-weak'
end
text = text .. '">{{'
if namePrefix then
text = text .. namePrefix
end
text = text .. '</span>'
if nav and currentTitle == titleObject then
text = text .. '\'\'\''
end
text = text .. '<span class="ts-templateCallCode-templateName" data-navboxnavigation-link="0">'
local commentedLabel
if comment then
-- https://phabricator.wikimedia.org/T200704
-- commentedLabel = mw.getCurrentFrame():expandTemplate({title = 'comment', args = {(textInPlaceOfName or name), comment}})
commentedLabel = '<span class="commentedText" title="' .. comment .. '" style="border-bottom: 1px dotted; cursor: help;">' ..
(textInPlaceOfName or name) ..
'</span>'
end
local label = (commentedLabel or textInPlaceOfName or name)
if not noLink then
if noRedirect then
text = text .. '<span class="plainlinks">'
end
text = text .. linkBegin .. linkBody .. linkDivider .. label .. linkEnd
if noRedirect then
text = text .. '</span>'
end
else
text = text .. label
end
text = text .. '</span>'
if nav and currentTitle == titleObject then
text = text .. '\'\'\''
end
if not flags.withoutParams then
if optpText then
text = text .. optpText
end
text = text .. addParams(args, {
spaced = spaced,
black = black,
nowiki = nowiki,
from = from
})
if spaced then
text = text .. ' '
end
end
text = text .. '<span class="'
if not spaced then
text = text .. ' ts-templateCallCode-closing'
end
if not black then
text = text .. ' ts-templateCallCode-weak'
end
text = text .. '">}}</span>'
if postfix then
text = text .. processText(postfix, nowiki)
end
if tag then
text = text .. '</' .. tag .. '>'
end
local ts = mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Модуль:Template call code/styles.css' } }
return ts .. text
end
function p._onlyParams(args)
local yesno = require('Module:Yesno')
return addParams(args, {
spaced = yesno(args._spaced, false),
black = true,
nowiki = yesno(args._nowiki, false),
from = 1
})
end
p.withoutParams = makeInvokeFunc('_main', {withoutParams = true})
p.withParams = makeInvokeFunc('_main', {withoutParams = false})
p.onlyParams = makeInvokeFunc('_onlyParams')
return p
c4cde66869b509219e9bf629a766ce30ad0bdf97
Модуль:Yesno
828
12
22
21
2025-01-25T21:00:07Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- Function allowing for consistent treatment of boolean-like wikitext input.
-- It works similarly to the template {{yesno}}.
return function (val, default)
-- If your wiki uses non-ascii characters for any of "yes", "no", etc., you
-- should replace "val:lower()" with "mw.ustring.lower(val)" in the
-- following line.
val = type(val) == 'string' and val:lower() or val
if val == nil then
return nil
elseif val == true
or val == 'yes'
or val == 'y'
or val == 'true'
or val == 't'
or val == 'да'
or val == 'д'
-- кириллица
or val == 'у'
or val == '+'
or tonumber(val) == 1
then
return true
elseif val == false
or val == 'no'
or val == 'n'
or val == 'false'
or val == 'f'
or val == 'нет'
or val == 'н'
or val == '-'
or tonumber(val) == 0
then
return false
else
return default
end
end
ae94e12a838e770797317ed07b57b330ffeb7658
Модуль:Template call code/styles.css
828
13
24
23
2025-01-25T21:00:08Z
Vallenland
2
1 версия импортирована
text
text/plain
.ts-templateCallCode-weak {
color: #72777d;
}
.ts-templateCallCode-pipe {
margin: 0 2px;
}
.ts-templateCallCode-pipe + .ts-templateCallCode-pipe,
/* Template:Optp */
.ts-templateCallCode-pipe + .ts-templateCallCode-param > .ts-templateCallCode-weak:first-child > .ts-templateCallCode-pipe:first-child {
margin-left: 0;
}
.ts-templateCallCode-param + .ts-templateCallCode-closing {
margin-left: 2px;
}
span.ts-templateCallCode > .ts-templateCallCode-templateName a {
/* Решение из https://ru.wikipedia.org/wiki/Шаблон:Фиттс */
padding: 0 0.5em !important; /* Перезаписываем стиль для .plainlinks a.external */
position: relative;
margin: -0.5em;
}
/* [[Категория:Шаблоны:Подстраницы CSS]] */
b3ed166240cf28c48a58b8d992794b753b2c6ef5
Модуль:Message box
828
14
26
25
2025-01-25T21:00:08Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- This is a meta-module for producing message box templates, including
-- {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.
-- Load necessary modules.
require('strict')
local getArgs
local categoryHandler = require('Module:Category handler')._main
local yesno = require('Module:Yesno')
local boxDate = require('Module:Calendar').bxDate;
-- Get a language object for formatDate and ucfirst.
local lang = mw.language.getContentLanguage()
-- Define constants
local CONFIG_MODULE = 'Module:Message box/configuration'
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getTitleObject(...)
-- Get the title object, passing the function through pcall
-- in case we are over the expensive function count limit.
local success, title = pcall(mw.title.new, ...)
if success then
return title
end
end
local function union(t1, t2)
-- Returns the union of two arrays.
local vals = {}
for i, v in ipairs(t1) do
vals[v] = true
end
for i, v in ipairs(t2) do
vals[v] = true
end
local ret = {}
for k in pairs(vals) do
table.insert(ret, k)
end
table.sort(ret)
return ret
end
local function getArgNums(args, prefix)
local nums = {}
for k, v in pairs(args) do
local num = mw.ustring.match(tostring(k), '^' .. prefix .. '([1-9]%d*)$')
if num then
table.insert(nums, tonumber(num))
end
end
table.sort(nums)
return nums
end
-- локальная обёртка, игнорирует таблицу с номерами дня, месяца и года
local function formatDate(txtDateIn, strFormat, params)
local txtDateOut, date, status = boxDate(txtDateIn, strFormat, params)
if status.brk then
return error(status.errorText)
else
return txtDateOut
end
end
--------------------------------------------------------------------------------
-- Box class definition
--------------------------------------------------------------------------------
local MessageBox = {}
MessageBox.__index = MessageBox
function MessageBox.new(boxType, args, cfg)
args = args or {}
local obj = {}
-- Set the title object and the namespace.
obj.title = getTitleObject(args.page) or mw.title.getCurrentTitle()
-- Set the config for our box type.
obj.cfg = cfg[boxType]
if not obj.cfg then
local ns = obj.title.namespace
-- boxType is "mbox" or invalid input
if ns == 0 then
obj.cfg = cfg.ambox -- main namespace
elseif ns == 6 then
obj.cfg = cfg.imbox -- file namespace
elseif ns == 14 then
obj.cfg = cfg.cmbox -- category namespace
else
local nsTable = mw.site.namespaces[ns]
if nsTable and nsTable.isTalk then
obj.cfg = cfg.tmbox -- any talk namespace
else
obj.cfg = cfg.ombox -- other namespaces or invalid input
end
end
end
-- Set the arguments, and remove all blank arguments except for the ones
-- listed in cfg.allowBlankParams.
do
local newArgs = {}
for k, v in pairs(args) do
if v ~= '' then
newArgs[k] = v
end
end
for i, param in ipairs(obj.cfg.allowBlankParams or {}) do
newArgs[param] = args[param]
end
obj.args = newArgs
end
-- Define internal data structure.
obj.categories = {}
obj.classes = {}
return setmetatable(obj, MessageBox)
end
function MessageBox:addCat(ns, cat, sort)
if not cat then
return nil
end
if sort then
cat = string.format('[[Категория:%s|%s]]', cat, sort)
else
cat = string.format('[[Категория:%s]]', cat)
end
self.categories[ns] = self.categories[ns] or {}
table.insert(self.categories[ns], cat)
end
function MessageBox:addClass(class)
if not class then
return nil
end
table.insert(self.classes, class)
end
function MessageBox:setParameters()
local args = self.args
local cfg = self.cfg
-- Get type data.
self.type = args.type
local typeData = cfg.types[self.type]
self.invalidTypeError = cfg.showInvalidTypeError
and self.type
and not typeData
typeData = typeData or cfg.types[cfg.default]
self.typeClass = typeData.class
self.typeImage = typeData.image
-- Find if the box has been wrongly substituted.
self.isSubstituted = cfg.substCheck and args.subst == 'SUBST'
-- Find whether we are using a small message box.
self.isSmall = cfg.allowSmall and (
cfg.smallParam and args.small == cfg.smallParam
or not cfg.smallParam and yesno(args.small)
)
-- Add attributes, classes and styles.
self.id = args.id
self.name = args.name
if self.name then
self:addClass('mbox-' .. string.gsub(self.name,' ','_'))
end
if yesno(args.plainlinks) ~= false then
self:addClass('plainlinks')
end
for _, class in ipairs(cfg.classes or {}) do
self:addClass(class)
end
if self.isSmall then
self:addClass(cfg.smallClass or 'mbox-small')
end
self:addClass(self.typeClass)
self:addClass(args.class)
self.style = args.style
self.attrs = args.attrs
self.dataLabel1 = args['data-label-1']
self.dataLabel2 = args['data-label-2']
self.dataLabel3 = args['data-label-3']
self.dataValue1 = args['data-value-1']
self.dataValue2 = args['data-value-2']
self.dataValue3 = args['data-value-3']
-- Set text style.
self.textstyle = args.textstyle
-- Find if we are on the template page or not. This functionality is only
-- used if useCollapsibleTextFields is set, or if both cfg.templateCategory
-- and cfg.templateCategoryRequireName are set.
self.useCollapsibleTextFields = cfg.useCollapsibleTextFields
if self.useCollapsibleTextFields
or cfg.templateCategory
and cfg.templateCategoryRequireName
then
self.name = args.name
if self.name then
local templateName = mw.ustring.match(
self.name,
'^[tT][eE][mM][pP][lL][aA][tT][eE][%s_]*:[%s_]*(.*)$'
) or self.name
templateName = ('Template:' .. templateName) or ('Шаблон:' .. templateName)
self.templateTitle = getTitleObject(templateName)
end
self.isTemplatePage = self.templateTitle
and mw.title.equals(self.title, self.templateTitle)
end
-- Process data for collapsible text fields. At the moment these are only
-- used in {{ambox}}.
if self.useCollapsibleTextFields then
-- Get the self.issue value.
if self.isSmall and args.smalltext then
self.issue = args.smalltext
else
if args.sect and args.sect ~= '' or nil then
local issue_sect = args.issue_sect
issue_sect = type(issue_sect) == 'string' and issue_sect ~= '' and issue_sect or nil
local text_sect = args.text_sect
text_sect = type(text_sect) == 'string' and text_sect ~= '' and text_sect or nil
local issues = {}
table.insert(issues, issue_sect)
table.insert(issues, text_sect)
self.issue = table.concat(issues, ' ')
else
local issue = args.issue
issue = type(issue) == 'string' and issue ~= '' and issue or nil
local text = args.text
text = type(text) == 'string' and text or nil
local issues = {}
table.insert(issues, issue)
table.insert(issues, text)
self.issue = table.concat(issues, ' ')
end
end
-- Get the self.talk value.
local talk = args.talk
-- Show talk links on the template page or template subpages if the talk
-- parameter is blank.
if talk == ''
and self.templateTitle
and (
mw.title.equals(self.templateTitle, self.title)
or self.title:isSubpageOf(self.templateTitle)
)
then
talk = '#'
elseif talk == '' then
talk = nil
end
if talk then
-- If the talk value is a talk page, make a link to that page. Else
-- assume that it's a section heading, and make a link to the talk
-- page of the current page with that section heading.
local talkTitle = getTitleObject(talk)
local talkArgIsTalkPage = true
if not talkTitle or not talkTitle.isTalkPage then
talkArgIsTalkPage = false
talkTitle = getTitleObject(
self.title.text,
mw.site.namespaces[self.title.namespace].talk.id
)
end
if talkTitle and talkTitle.exists then
local talkText = 'Соответствующую дискуссию можно найти на'
if talkArgIsTalkPage then
talkText = string.format(
'%s [[%s|%s]].',
talkText,
talk,
talkTitle.prefixedText
)
else
talkText = string.format(
'%s [[%s#%s|странице обсуждения]].',
talkText,
talkTitle.prefixedText,
talk
)
end
self.talk = talkText
end
end
-- Get other values.
self.fix = args.fix ~= '' and args.fix or nil
local date
if args.date and args.date ~= '' then
local status, result = pcall(formatDate, args.date)
if status then
date = string.format("(<span class='date'>%s</span>)", result)
else
date = string.format("<span class='error'>(Строка «%s» не является верной датой, пожалуйста, укажите дату в формате <code>ГГГГ-ММ-ДД</code>)</span>", args.date)
end
elseif args.date == '' and self.isTemplatePage then
date = string.format("(<span class='date'>%s</span>)", formatDate( lang:formatDate('Y-m-d') ) ) -- тут возникновения ошибки, связанной с пользовательским вводом, не будет
end
if date then
self.date = string.format(" <span class='mbox-date'>''%s''</span>", date)
end
self.info = args.info
if yesno(args.removalnotice) then
self.removalNotice = cfg.removalNotice
end
if args.shortFix then
self.shortFix = args.shortFix
end
end
-- Set the non-collapsible text field. At the moment this is used by all box
-- types other than ambox, and also by ambox when small=yes.
if self.isSmall then
self.text = args.smalltext or args.text
else
self.text = args.text
self.textsmall = args['text-small']
end
-- Set the below row.
self.below = cfg.below and args.below
-- General image settings.
self.imageCellDiv = not self.isSmall and cfg.imageCellDiv
self.imageEmptyCell = cfg.imageEmptyCell
if cfg.imageEmptyCellStyle then
self.imageEmptyCellStyle = 'border:none;padding:0px;width:1px'
end
-- Left image settings.
local imageLeft = self.isSmall and args.smallimage or args.image
if cfg.imageCheckBlank and imageLeft ~= 'blank' and imageLeft ~= 'none' and imageLeft ~= ''
or not cfg.imageCheckBlank and imageLeft ~= 'none'
then
self.imageLeft = imageLeft
if not imageLeft then
local imageSize = self.isSmall
and (cfg.imageSmallSize or '30x30px')
or cfg.imageSize
or '40x40px'
self.imageLeft = string.format('[[File:%s|%s|alt=]]', self.typeImage
or 'Information icon4.svg', imageSize)
end
end
-- Right image settings.
local imageRight = self.isSmall and args.smallimageright or args.imageright
if not (cfg.imageRightNone and imageRight == 'none') then
self.imageRight = imageRight
end
-- set templatestyles
self.base_templatestyles = cfg.templatestyles
end
function MessageBox:setMainspaceCategories()
local args = self.args
local cfg = self.cfg
local date = nil
if not cfg.allowMainspaceCategories then
return nil
end
local nums = {}
for _, prefix in ipairs{'cat', 'category', 'all'} do
args[prefix .. '1'] = args[prefix]
nums = union(nums, getArgNums(args, prefix))
end
-- The following is roughly equivalent to the old {{Ambox/category}}.
local status, result = pcall(formatDate, args.date, 'xg Y')
if status then
date = result
end
date = type(date) == 'string' and date
local preposition = 'с'
local suffix = 'года'
for _, num in ipairs(nums) do
local mainCat = args['cat' .. tostring(num)]
or args['category' .. tostring(num)]
local allCat = args['all' .. tostring(num)]
mainCat = type(mainCat) == 'string' and mainCat
allCat = type(allCat) == 'string' and allCat
if mainCat and date and date ~= '' then
local catTitle = string.format('%s %s %s %s', mainCat, preposition, date, suffix)
self:addCat(0, catTitle)
catTitle = getTitleObject('Категория:' .. catTitle)
local status, result = pcall(formatDate, args.date)
if not status then
self:addCat(0, 'Википедия:Статьи с недопустимым параметром даты в шаблоне-сообщении')
end
elseif mainCat and (not date or date == '') then
self:addCat(0, mainCat)
end
if allCat then
self:addCat(0, allCat)
end
end
end
function MessageBox:setTemplateCategories()
local args = self.args
local cfg = self.cfg
-- Add template categories.
if cfg.templateCategory then
if cfg.templateCategoryRequireName then
if self.isTemplatePage then
self:addCat(10, cfg.templateCategory)
end
elseif not self.title.isSubpage then
self:addCat(10, cfg.templateCategory)
end
end
-- Add template error categories.
if cfg.templateErrorCategory then
local templateErrorCategory = cfg.templateErrorCategory
local templateCat, templateSort
if not self.name and not self.title.isSubpage then
templateCat = templateErrorCategory
elseif self.isTemplatePage then
local paramsToCheck = cfg.templateErrorParamsToCheck or {}
local count = 0
for i, param in ipairs(paramsToCheck) do
if not args[param] then
count = count + 1
end
end
if count > 0 then
templateCat = templateErrorCategory
templateSort = tostring(count)
end
if self.categoryNums and #self.categoryNums > 0 then
templateCat = templateErrorCategory
templateSort = 'C'
end
end
self:addCat(10, templateCat, templateSort)
end
end
function MessageBox:setAllNamespaceCategories()
-- Set categories for all namespaces.
if self.invalidTypeError then
local allSort = (self.title.namespace == 0 and 'Main:' or '') .. self.title.prefixedText
self:addCat('all', 'Википедия:Необходимо исправить параметр в шаблоне-сообщении', allSort)
end
if self.isSubstituted then
self:addCat('all', 'Википедия:Страницы с ошибочно подставленными шаблонами')
end
if self.isSmall then
self:addCat(0, 'Википедия:Страницы с малыми шаблонами-сообщениями')
end
end
function MessageBox:setCategories()
if self.title.namespace == 0 then
self:setMainspaceCategories()
elseif self.title.namespace == 10 then
self:setTemplateCategories()
end
self:setAllNamespaceCategories()
end
function MessageBox:renderCategories()
-- Convert category tables to strings and pass them through
-- [[Module:Category handler]].
return categoryHandler{
main = table.concat(self.categories[0] or {}),
template = table.concat(self.categories[10] or {}),
all = table.concat(self.categories.all or {}),
nocat = self.args.nocat,
page = self.args.page
}
end
function MessageBox:export()
local root = mw.html.create()
-- Add the subst check error.
if self.isSubstituted and self.name then
root:tag('b')
:addClass('error')
:wikitext(string.format(
'Шаблон <code>%s[[Шаблон:%s|%s]]%s</code> был неккоректно подставлен.',
mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}')
))
end
-- Conditional TemplateStyles loading
if self.base_templatestyles then
local frame = mw.getCurrentFrame()
root:wikitext(frame:extensionTag{
name = 'templatestyles',
args = { src = self.base_templatestyles },
})
end
-- Create the box table.
local boxTable = root:tag('table')
boxTable:attr('id', self.id or nil)
for i, class in ipairs(self.classes or {}) do
boxTable:addClass(class or nil)
end
boxTable
:cssText(self.style or nil)
:attr('role', 'presentation')
if self.dataLabel1 then
boxTable:attr('data-' .. self.dataLabel1, self.dataValue1)
end
if self.dataLabel2 then
boxTable:attr('data-' .. self.dataLabel2, self.dataValue2)
end
if self.dataLabel3 then
boxTable:attr('data-' .. self.dataLabel3, self.dataValue3)
end
if self.attrs then
boxTable:attr(self.attrs)
end
-- Add the left-hand image.
local row = boxTable:tag('tr')
if self.imageLeft then
local imageLeftCell = row:tag('td'):addClass('mbox-image')
if self.imageCellDiv then
-- If we are using a div, redefine imageLeftCell so that the image
-- is inside it. Divs use style="width: 52px;", which limits the
-- image width to 52px. If any images in a div are wider than that,
-- they may overlap with the text or cause other display problems.
imageLeftCell = imageLeftCell:tag('div'):css('width', '52px')
end
imageLeftCell:wikitext(self.imageLeft or nil)
elseif self.imageEmptyCell then
-- Some message boxes define an empty cell if no image is specified, and
-- some don't. The old template code in templates where empty cells are
-- specified gives the following hint: "No image. Cell with some width
-- or padding necessary for text cell to have 100% width."
row:tag('td')
:addClass('mbox-empty-cell')
:cssText(self.imageEmptyCellStyle or nil)
end
-- Add the text.
local textCell = row:tag('td'):addClass('mbox-text')
if self.useCollapsibleTextFields then
-- The message box uses advanced text parameters that allow things to be
-- collapsible. At the moment, only ambox uses this.
textCell:cssText(self.textstyle or nil)
local textCellDiv = textCell:tag('div')
textCellDiv
:addClass('mbox-text-div')
:wikitext(self.issue or nil)
local textsmallCellDiv = textCell:tag('div')
textsmallCellDiv
:addClass('mbox-textsmall-div hide-when-compact')
:cssText(self.textsmallstyle)
:wikitext(self.textsmall or nil)
if (self.talk or self.fix) and not self.isSmall then
textsmallCellDiv:tag('span')
:addClass('hide-when-compact')
:wikitext(self.fix and (' ' .. self.fix) or nil)
:wikitext(self.talk and (' ' .. self.talk) or nil)
end
if self.textsmall or self.fix or self.talk then
textsmallCellDiv:wikitext(self.date and (' ' .. self.date) or nil)
else
textCellDiv:wikitext(self.date and (' ' .. self.date) or nil)
end
if self.info and not self.isSmall then
textsmallCellDiv
:tag('span')
:addClass('hide-when-compact')
:wikitext(self.info and (' ' .. self.info) or nil)
end
if self.removalNotice then
textsmallCellDiv:tag('small')
:addClass('hide-when-compact')
:tag('i')
:wikitext(string.format(" (%s)", self.removalNotice))
end
if self.shortFix then
textCell:tag('div')
:addClass('mbox-multiply')
:tag('span')
:wikitext(string.format("%s", self.shortFix))
:tag('span')
:wikitext(self.date and (' ' .. self.date) or nil)
end
else
-- Default text formatting - anything goes.
textCell
:cssText(self.textstyle or nil)
:wikitext(self.text or nil)
end
-- Add the right-hand image.
if self.imageRight then
local imageRightCell = row:tag('td'):addClass('mbox-imageright')
if self.imageCellDiv then
-- If we are using a div, redefine imageRightCell so that the image
-- is inside it.
imageRightCell = imageRightCell:tag('div'):css('width', '52px')
end
imageRightCell
:wikitext(self.imageRight or nil)
end
-- Add the below row.
if self.below then
boxTable:tag('tr')
:tag('td')
:attr('colspan', self.imageRight and '3' or '2')
:addClass('mbox-text')
:cssText(self.textstyle or nil)
:wikitext(self.below or nil)
end
-- Add error message for invalid type parameters.
if self.invalidTypeError then
root:tag('div')
:css('text-align', 'center')
:wikitext(string.format(
'Этот шаблон-сообщение использует неверный параметр "type=%s", необходимо исправить.',
self.type or ''
))
end
-- Add categories.
root:wikitext(self:renderCategories() or nil)
return tostring(root)
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p, mt = {}, {}
function p._exportClasses()
-- For testing.
return {
MessageBox = MessageBox
}
end
function p.main(boxType, args, cfgTables)
local box = MessageBox.new(boxType, args, cfgTables or mw.loadData(CONFIG_MODULE))
box:setParameters()
box:setCategories()
return box:export()
end
function mt.__index(t, k)
return function (frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
return t.main(k, getArgs(frame, {trim = false, removeBlanks = false}))
end
end
return setmetatable(p, mt)
f2539b657a9cdadde7c0dd5ad270d3095b2bdd54
Модуль:Category handler
828
15
28
27
2025-01-25T21:00:09Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--------------------------------------------------------------------------------
-- --
-- CATEGORY HANDLER --
-- --
-- This module implements the {{category handler}} template in Lua, --
-- with a few improvements: all namespaces and all namespace aliases --
-- are supported, and namespace names are detected automatically for --
-- the local wiki. This module requires [[Module:Namespace detect]] --
-- and [[Module:Yesno]] to be available on the local wiki. It can be --
-- configured for different wikis by altering the values in --
-- [[Module:Category handler/config]], and pages can be blacklisted --
-- from categorisation by using [[Module:Category handler/blacklist]]. --
-- --
--------------------------------------------------------------------------------
-- Load required modules
local yesno = require('Module:Yesno')
-- Lazily load things we don't always need
local mShared, mappings
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function trimWhitespace(s, removeBlanks)
if type(s) ~= 'string' then
return s
end
s = s:match('^%s*(.-)%s*$')
if removeBlanks then
if s ~= '' then
return s
else
return nil
end
else
return s
end
end
--------------------------------------------------------------------------------
-- CategoryHandler class
--------------------------------------------------------------------------------
local CategoryHandler = {}
CategoryHandler.__index = CategoryHandler
function CategoryHandler.new(data, args)
local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)
-- Set the title object
do
local pagename = obj:parameter('demopage')
local success, titleObj
if pagename then
success, titleObj = pcall(mw.title.new, pagename)
end
if success and titleObj then
obj.title = titleObj
if titleObj == mw.title.getCurrentTitle() then
obj._usesCurrentTitle = true
end
else
obj.title = mw.title.getCurrentTitle()
obj._usesCurrentTitle = true
end
end
-- Set suppression parameter values
for _, key in ipairs{'nocat', 'categories'} do
local value = obj:parameter(key)
value = trimWhitespace(value, true)
obj['_' .. key] = yesno(value)
end
do
local subpage = obj:parameter('subpage')
local category2 = obj:parameter('category2')
if type(subpage) == 'string' then
subpage = mw.ustring.lower(subpage)
end
if type(category2) == 'string' then
subpage = mw.ustring.lower(category2)
end
obj._subpage = trimWhitespace(subpage, true)
obj._category2 = trimWhitespace(category2) -- don't remove blank values
end
return obj
end
function CategoryHandler:parameter(key)
local parameterNames = self._data.parameters[key]
local pntype = type(parameterNames)
if pntype == 'string' or pntype == 'number' then
return self._args[parameterNames]
elseif pntype == 'table' then
for _, name in ipairs(parameterNames) do
local value = self._args[name]
if value ~= nil then
return value
end
end
return nil
else
error(string.format(
'invalid config key "%s"',
tostring(key)
), 2)
end
end
function CategoryHandler:isSuppressedByArguments()
return
-- See if a category suppression argument has been set.
self._nocat == true
or self._categories == false
or (
self._category2
and self._category2 ~= self._data.category2Yes
and self._category2 ~= self._data.category2Negative
)
-- Check whether we are on a subpage, and see if categories are
-- suppressed based on our subpage status.
or self._subpage == self._data.subpageNo and self.title.isSubpage
or self._subpage == self._data.subpageOnly and not self.title.isSubpage
end
function CategoryHandler:shouldSkipBlacklistCheck()
-- Check whether the category suppression arguments indicate we
-- should skip the blacklist check.
return self._nocat == false
or self._categories == true
or self._category2 == self._data.category2Yes
end
function CategoryHandler:matchesBlacklist()
if self._usesCurrentTitle then
return self._data.currentTitleMatchesBlacklist
else
mShared = mShared or require('Module:Category handler/shared')
return mShared.matchesBlacklist(
self.title.prefixedText,
mw.loadData('Module:Category handler/blacklist')
)
end
end
function CategoryHandler:isSuppressed()
-- Find if categories are suppressed by either the arguments or by
-- matching the blacklist.
return self:isSuppressedByArguments()
or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()
end
function CategoryHandler:getNamespaceParameters()
if self._usesCurrentTitle then
return self._data.currentTitleNamespaceParameters
else
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
return mShared.getNamespaceParameters(
self.title,
mappings
)
end
end
function CategoryHandler:namespaceParametersExist()
-- Find whether any namespace parameters have been specified.
-- We use the order "all" --> namespace params --> "other" as this is what
-- the old template did.
if self:parameter('all') then
return true
end
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
for ns, params in pairs(mappings) do
for i, param in ipairs(params) do
if self._args[param] then
return true
end
end
end
if self:parameter('other') then
return true
end
return false
end
function CategoryHandler:getCategories()
local params = self:getNamespaceParameters()
local nsCategory
for i, param in ipairs(params) do
local value = self._args[param]
if value ~= nil then
nsCategory = value
break
end
end
if nsCategory ~= nil or self:namespaceParametersExist() then
-- Namespace parameters exist - advanced usage.
if nsCategory == nil then
nsCategory = self:parameter('other')
end
local ret = {self:parameter('all')}
local numParam = tonumber(nsCategory)
if numParam and numParam >= 1 and math.floor(numParam) == numParam then
-- nsCategory is an integer
ret[#ret + 1] = self._args[numParam]
else
ret[#ret + 1] = nsCategory
end
if #ret < 1 then
return nil
else
return table.concat(ret)
end
elseif self._data.defaultNamespaces[self.title.namespace] then
-- Namespace parameters don't exist, simple usage.
return self._args[1]
end
return nil
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
-- Used for testing purposes.
return {
CategoryHandler = CategoryHandler
}
end
function p._main(args, data)
data = data or mw.loadData('Module:Category handler/data')
local handler = CategoryHandler.new(data, args)
if handler:isSuppressed() then
return nil
end
return handler:getCategories()
end
function p.main(frame, data)
data = data or mw.loadData('Module:Category handler/data')
local args = require('Module:Arguments').getArgs(frame, {
wrappers = data.wrappers,
valueFunc = function (k, v)
v = trimWhitespace(v)
if type(k) == 'number' then
if v ~= '' then
return v
else
return nil
end
else
return v
end
end
})
return p._main(args, data)
end
return p
b74dd63857b24904ac452429b11213f18647471f
Модуль:Calendar
828
16
30
29
2025-01-25T21:00:09Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local p = {}
-- Необходимые модули и переменные
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local mwlang = mw.getContentLanguage()
local err = "―" -- NthDay nil result
local tCon = table.concat
-- 00) Блок многократно используемых списков
local bool_to_number={ [true]=1, [false]=0 }
local monthlang = {"января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"}
local month_to_num = {["января"]=1,["февраля"]=2,["марта"]=3,["апреля"]=4,["мая"]=5,["июня"]=6,
["июля"]=7,["августа"]=8,["сентября"]=9,["октября"]=10,["ноября"]=11,["декабря"]=12,["-"]=""}
local monthd = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
local params = { {"г", "g"}, {"ю", "j"}}
local comment = { '<span style="border-bottom: 1px dotted; cursor: help" title="по юлианскому календарю">','</span>'}
-- duplicates:
-- AST, BST, CST, ECT, IST, MST, PST, SST,
local known_tzs = {
ACDT='+10:30', ACST='+09:30', ACT ='+08:00', ADT ='-03:00', AEDT ='+11:00',
AEST='+10:00', AFT ='+04:30', AKDT='-08:00', AKST ='-09:00', AMST ='+05:00',
AMT ='+04:00', ART ='-03:00', AST ='+03:00', AST ='+04:00', AST ='+03:00',
AST ='-04:00', AWDT='+09:00', AWST='+08:00', AZOST='-01:00', AZT ='+04:00',
BDT ='+08:00', BIOT='+06:00', BIT ='-12:00', BOT ='-04:00', BRT ='-03:00',
BST ='+06:00', BST ='+01:00', BTT ='+06:00', CAT ='+02:00', CCT ='+06:30',
CDT ='-05:00', CEDT='+02:00', CEST='+02:00', CET ='+01:00', CHAST='+12:45',
CIST='-08:00', CKT ='-10:00', CLST='-03:00', CLT ='-04:00', COST ='-04:00',
COT ='-05:00', CST ='-06:00', CST ='+08:00', CVT ='-01:00', CXT ='+07:00',
CHST='+10:00', DFT ='+01:00', EAST='-06:00', EAT ='+03:00', ECT ='-04:00',
ECT ='-05:00', EDT ='-04:00', EEDT='+03:00', EEST ='+03:00', EET ='+02:00',
EST ='-05:00', FJT ='+12:00', FKST='-03:00', FKT ='-04:00', GALT ='-06:00',
GET ='+04:00', GFT ='-03:00', GILT='+12:00', GIT ='-09:00', GMT ='+00:00',
GST ='-02:00', GYT ='-04:00', HADT='-09:00', HAST ='-10:00', HKT ='+08:00',
HMT ='+05:00', HST ='-10:00', IRKT='+08:00', IRST ='+03:30', IST ='+05:30',
IST ='+01:00', IST ='+02:00', JST ='+09:00', KRAT ='+07:00', KST ='+09:00',
LHST='+10:30', LINT='+14:00', MAGT='+11:00', MDT ='-06:00', MIT ='-09:30',
MSD ='+04:00', MSK ='+03:00', MST ='+08:00', MST ='-07:00', MST ='+06:30',
MUT ='+04:00', NDT ='-02:30', NFT ='+11:30', NPT ='+05:45', NST ='-03:30',
NT ='-03:30', OMST='+06:00', PDT ='-07:00', PETT ='+12:00', PHOT ='+13:00',
PKT ='+05:00', PST ='-08:00', PST ='+08:00', RET ='+04:00', SAMT ='+04:00',
SAST='+02:00', SBT ='+11:00', SCT ='+04:00', SLT ='+05:30', SST ='-11:00',
SST ='+08:00', TAHT='-10:00', THA ='+07:00', UTC ='+00:00', UYST ='-02:00',
UYT ='-03:00', VET ='-04:30', VLAT='+10:00', WAT ='+01:00', WEDT ='+01:00',
WEST='+01:00', WET ='+00:00', YAKT='+09:00', YEKT ='+05:00',
-- US Millitary (for RFC-822)
Z='+00:00', A='-01:00', M='-12:00', N='+01:00', Y='+12:00',
}
local category = {
["no_parameters"]=
"<!--[[Категория:Модуль:Calendar:Страницы без параметров]]-->",
["incomplete_parameters"]=
"<!--[[Категория:Модуль:Calendar:Страницы с неполными или некорректными параметрами]]-->",
["without_verification"]=
"<!--[[Категория:Модуль:Calendar:Страницы без проверки параметров]]-->",
["erroneous_parameters"]=
"<!--[[Категория:Модуль:Calendar:Страницы с ошибочными параметрами]]-->"
}
-- несколько параметров передаются вместе с кодом ошибки в таблице, один может быть передан простым значением
local e = {
["start"]="<span class=error>Ошибка: ",
["ending"]=".</span>",
["no_pattern_match"]="строка «%s» не совпадает с заданными паттернами",
["no_valid_date"]="дата «%s» не является корректной",
["wrong_jd"]="юлианская дата %s вне диапазона",
["no_data"]="нет входящих данных",
["too_many_arguments"]="ожидается менее %i аргументов",
["too_little_arguments"]="ожидается более %i аргументов",
["wrong_calculation"]="даты %s и %s не прошли проверку, %s дней разница",
["unknown_param"]="параметр %s неизвестен",
["unknown_error"]="неизвестная ошибка",
["tech_error"]="ошибка в функции %s",
["box_date"]="строка «%s» не является верной датой, пожалуйста, укажите дату в формате ГГГГ-ММ-ДД"
-- [""]="",
}
local tzs_names = {"ACDT","ACST","ACT","ADT","AEDT","AEST","AFT","AKDT","AKST",
"AMST","AMT","ART","AST","AST","AST","AST","AWDT","AWST","AZOST","AZT","BDT",
"BIOT","BIT","BOT","BRT","BST","BST","BTT","CAT","CCT","CDT","CEDT","CEST",
"CET","CHAST","CIST","CKT","CLST","CLT","COST","COT","CST","CST","CVT","CXT",
"CHST","DFT","EAST","EAT","ECT","ECT","EDT","EEDT","EEST","EET","EST","FJT",
"FKST","FKT","GALT","GET","GFT","GILT","GIT","GMT","GST","GYT","HADT","HAST",
"HKT","HMT","HST","IRKT","IRST","IST","IST","IST","JST","KRAT","KST","LHST",
"LINT","MAGT","MDT","MIT","MSD","MSK","MST","MST","MST","MUT","NDT","NFT",
"NPT","NST","NT","OMST","PDT","PETT","PHOT","PKT","PST","PST","RET","SAMT",
"SAST","SBT","SCT","SLT","SST","SST","TAHT","THA","UTC","UYST","UYT","VET",
"VLAT","WAT","WEDT","WEST","WET","YAKT","YEKT","Z","A","M","N","Y","MSK"}
local pattern = { -- для распознавания дат, переданных одним строчным параметром
{"(-?%d%d%d%d?)[-%.%s/\\](%d%d)[-%.%s/\\](%d%d)", ["order"] = {3,2,1} }, -- yyyy mm dd
{"(%d+)[-%.%s/\\](%d+)[-%.%s/\\](%d%d%d%d?)", ["order"] = {1,2,3} }, -- dd mm yyyy
{"(%d%d)[-%.%s/\\](%d%d%d%d?)", ["order"] = {2,3} }, -- mm yyyy
{"(%d%d%d%d?)[-%.%s/\\](%d%d)", ["order"] = {3,2} }, -- yyyy mm
{"(%d+)%s(%l+)%s(%d%d%d%d?)", ["order"] = {1,2,3} }, -- d mmm y
{"(%l+)%s(%d+),?%s(%d%d%d%d?)", ["order"] = {2,1,3} }, -- mmm d, y
{"(%l+)%s(%d%d%d%d?)", ["order"] = {2,3} }, -- mmm y
}
local time_units = {"year","month","day"} --не используется
--[[ local time_units = {"second", "minute", "hour",
"day_of_month", "day_of_week", "day_of_year",
"week", "month", "year", "year_of_century", "century"} ]]--
-- напоминание чтобы сделать более точные пересчёты - с часами / расчёт длительностей периодов
local mnlang = {"ru_G", "ru_N", "en", "en_S", "de", "fr"}
local month_lang = {
["ru_G"] = {"января","февраля","марта","апреля","мая","июня",
"июля","августа","сентября","октября","ноября","декабря"},
["ru_N"] = {"январь","февраль","март","апрель","май","июнь",
"июль","август","сентябрь","октябрь","ноябрь","декабрь"},
["en"] = {"january", "february", "march", "april", "may", "june",
"july", "august", "september", "october", "november", "december"},
["en_S"] = {"jan", "feb", "mar", "apr", "may", "jun",
"jul", "aug", "sep", "oct", "nov", "dec"},
["de"] = {"januar", "februar", "märz", "april", "mai", "juni",
"juli", "august", "september", "oktober", "november", "dezember"},
["fr"] = {"janvier", "février", "mars", "avril", "mai", "juin",
"juillet", "août", "septembre", "octobre", "novembre", "décembre"}
}
-- заполняется автоматически
local reverse_month_lang = {}
-- вспомогательная функция для обращения таблиц (смена ключей со значениями)
local reverse_table = function (strait_table)
local reversed_table = {}
for k,v in pairs(strait_table) do
reversed_table[v] = k
end
return reversed_table
end
-- запуск цикла по заполнению обратных таблиц, необходимых для распознавания дат
local filling_months = function (mnlang, month_lang)
for i=1, #mnlang do
reverse_month_lang[mnlang[i]] = reverse_table(month_lang[mnlang[i]])
end
end
-- 10) Блок общих функций
local function trim(str)
if not str then return nil
else return str:match'^()%s*$' and '' or str:match'^%s*(.*%S)'
end
end
local function purif(str)
if str == "" or str == nil then
return nil
elseif type(tonumber(str)) == "number" then
return math.floor(tonumber(str))
else
return nil
end
-- need .5 -- ,5 number format converter?
end
local function is(str)
if (not str) or (str == "") then return false
else return yesno(str,false)
end
end
local function init(num)
local output = {}
for i=1,num do
table.insert(output, {["year"]="", ["month"]="", ["day"]=""})
end
return unpack(output)
end
local function isyear(tbl)
if type(tbl) ~= 'table' then return false
elseif not tbl["year"] then return false
elseif type(tbl["year"]) == 'number' then return true
else return false
end
end
local function inbord(val, down, up)
return not (type(up) ~= "number" or type(down) ~= "number" or type(val) ~= "number" or up < down or val < down or val > up)
end
local function shallowcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in pairs(orig) do
copy[orig_key] = orig_value
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
local inlist = function ( var, list )
local n = #list
local inlist = false
for i=1,n do
if var == list[i] then inlist = true end
end
return inlist
end
-- 20) Блок общих проверочных функций, связанных с датами
local function unwarp(tbl)
if not tbl then return ""
elseif type(tbl) ~= "table" then return tbl
elseif (tbl.day or tbl.month or tbl.year) then
return (tbl.year or "?").."-"..(tbl.month or "?").."-"..(tbl.day or "?")
else return (tbl[3] or "?").."-"..(tbl[2] or "?").."-"..(tbl[1] or "?")
end
end
local function leap_year(y,jul)
if (not y) or (type(y) ~= "number")
then return false
elseif (y % 4) ~= 0
then return false
elseif not jul and (y % 100 == 0 and y % 400 ~= 0)
then return false
else return true
end
end
-- функция для вычисления последнего дня месяца для юлианского и григорианского календарей
local function month_end_day (month,year,is_julian)
local month_end_day = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} -- если не задан год, дата 29 февраля считается допустимой
if not month or type(month) ~= "number" or month < 1 or month > 12 then return nil
elseif month ~= 2 or not year then return month_end_day[month]
elseif month == 2 and (year % 4) == 0 and not ((not is_julian) and (year % 100 == 0 and year % 400 ~= 0)) then return 29
elseif month == 2 then return 28
else return nil -- в случае не целого значения входящих параметров или при иных непредусмотренных событиях
end
end
local function isdate ( chain , jul ) -- можно использовать для проверки таблиц с полями day, month, year
if not chain then return false
elseif (not type(chain) == "table")
or (not inbord(chain.year,-9999,9999))
or (not inbord(chain.month,1,12))
or (not inbord(chain.day,1,31))
or chain.day > monthd[chain.month]
-- or chain.year == 0
then return false
elseif chain.month == 2 and chain.day == 29 and not leap_year(chain.year,jul)
then return false
else return true end
-- check for other calendars needed?
end
local function ispartdate ( chain )
if not chain then return false
elseif not (type(chain) == "table") then return false
elseif (inbord(chain.year,-9999,9999)
or inbord(chain.month,1,12)
or inbord(chain.day,1,31)) then return true
else return false
end
-- partial date
-- more detailed check for 31.02.0000 needed
-- check for other calendars needed
end
-- from date1 to date2 in one year (beetwen jan-dec, dec-jan needed)
local function partdist(date1,date2)
local mont, dist = 0, 0
local d1d, d1m, d2d, d2m = (date1["day"] or ""), (date1["month"] or ""),(date2["day"] or ""), (date2["month"] or "")
if not (inbord(d1d,1,31) and inbord(d2d,1,31)) then return false end
-- нужна доп. проверка частичных дат на корректность
if (inbord(d1m,1,12) or inbord(d2m,1,12))
and (d1m == "" or d2m == "") then
mont = purif(date1["month"] or date2["month"])
d1m, d2m = mont, mont
end
-- mw.log("📏 day: " ..d1d .."->"..d2d.." month: ".. d1m.."->"..d2m )
if (inbord(d1m,1,12) and d1d <= monthd[d1m])
and (inbord(d2m,1,12) and d2d <= monthd[d2m]) then
if d2m == d1m
then dist = d2d - d1d
else dist = monthd[d1m] - d1d + d2d
end
return dist
else return math.huge
end
end
local function dmdist(d1,d2)
local p1,p2 = math.huge,math.huge
if not not partdist(d1,d2) then
p1=partdist(d1,d2)
end
if not not partdist(d2,d1) then
p1=partdist(d2,d1)
end
-- if (not p1) or (not p2) then
-- return (p1 or "") .. (p2 or "")
-- else
-- mw.log("d1, d2 = " .. undate(d1) .. ", " .. undate(d2))
return math.min(tonumber(partdist(d1,d2)) or math.huge,tonumber(partdist(d2,d1)) or math.huge)
-- end
end
-- 30) Блок функций для обработки ввода-вывода дат
local function undate(tbl)
if not tbl then return ""
else return (tbl.year or "").."-"..(tbl.month or "").."-"..(tbl.day or "")
end
end
-- функция для нормализации значений дат и перевода месяцев в числа
local function numerize(str)
if type(str) == "number" then
return math.floor(str)
elseif str == "" or str == nil or type(str) ~= "string" then
return nil
elseif type(tonumber(str)) == "number" then
return math.floor(tonumber(str))
else
for i=1, #mnlang do
if inlist(mw.ustring.lower(str),month_lang[mnlang[i]]) then
return reverse_month_lang[mnlang[i]][mw.ustring.lower(str)]
end
end
end
end
-- функция распознавания даты, переданной одной строкой
local function parse_date(date_string)
if type(date_string) ~= "string" or date_string == "" then return nil end
local out_date_str = {"","",""}
local error_data = {}
for i=1, #pattern do
local result_1, result_2, result_3 = mw.ustring.match(mw.ustring.lower(date_string),pattern[i][1])
if (result_1 or "") > "" then
out_date_str[pattern[i].order[1]] = result_1
out_date_str[pattern[i].order[2]] = result_2
if (pattern[i].order[3]) then out_date_str[pattern[i].order[3]] = result_3 end
-- mw.log("Паттерн " .. i .. ", строка: " .. date_string)
break
end
end
local date = {
["day"] =numerize(out_date_str[1]),
["month"]=numerize(out_date_str[2]),
["year"] =numerize(out_date_str[3])}
return date --, error_data
end
----[[ УСТАРЕЛО ]]----
local numstr2date = function(numstr)
local format = "Y-m-d"
local iso_date = mwlang:formatDate(format,numstr)
local y,m,d = string.match(iso_date, "(%d+)-(%d+)-(%d+)")
local dateout = {["year"]=purif(y), ["month"]=purif(m), ["day"]=purif(d)}
return dateout
end
--local numstr2date = function(numstr)
-- local nums = {}
-- local dateout = {}
-- for num in string.gmatch(numstr,"(%d+)") do
-- table.insert(nums,purif(num))
-- end
-- if #nums ~= 3 then error("В поле даты вместо трёх чисел с разделителями указано " .. #nums)
-- elseif not inbord(nums[2],1,12) then error("Месяц с номером " .. nums[2] .. " не найден")
-- elseif not inbord(nums[3],1,31) then
-- dateout = {["year"]=nums[3], ["month"]=nums[2], ["day"]=nums[1]}
-- elseif not inbord(nums[1],1,31) then
-- dateout = {["year"]=nums[1], ["month"]=nums[2], ["day"]=nums[3]}
-- elseif inbord(nums[1],1,31) then
-- dateout = {["year"]=nums[3], ["month"]=nums[2], ["day"]=nums[1]}
-- else
-- local mwlang = mw.getContentLanguage()
-- implement mwlang:formatDate(format,datein,true) here
-- return error("Не распознано " .. numstr .. " как дата")
-- end
-- return dateout
--end
local function year2lang(numyear,yearmark,wiki)
if not numyear then return "" end
if not yearmark then yearmark = "" end
local output = ""
local bcmark = " до н. э."
if numyear > 0 then bcmark = ""
else numyear = 1 - numyear end
if wiki then
-- output = tCon({'[[', numyear,' год',bcmark,'|', numyear,']]', " ", yearmark, " ", bcmark})
output = tCon({'[[', numyear,' год',bcmark,'|', trim(numyear .. " " .. yearmark .. " " .. bcmark), ']]'})
else
output = tCon({numyear, " ", yearmark, bcmark})
end
return trim(output)
end
local function day2lang(datein,wikidate,wiki,inner_brt)
-- if not isdate(wikidate) then wiki = false end
if not ispartdate(datein) then return "" end
local dm_separ, output = "", nil
if (not (not datein.day)) and (not (not datein.month)) then dm_separ = " " end
if (not datein.month) then datein.month = "" end
if (not datein.day) then datein.day = "" end
local monlan = monthlang[datein.month] or ""
if wiki and not inner_brt then
output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "",
"|", (datein.day or ""), dm_separ, monlan, "]]"})
elseif wiki then
output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "",
"|", (datein.day or ""), dm_separ, monlan})
else
output = tCon({datein.day, dm_separ, monlan})
end
return trim(output)
end
local function triple_txt2date(d,m,y)
-- добавить (args[1]:match("(%a+)") or "-") для нестандартной записи
-- mw.ustring.match((m or ""),"(%a+)")
local msg = ""
local year = purif((y or "-"):match("(%d+)"))
local month = purif(month_to_num[string.lower(mw.ustring.match((m or ""),"(%a+)"))])
local day = purif((d or "-"):match("(%d+)"))
if not month then
msg = category.incomplete_parameters
month = purif(month_to_num[string.lower(mw.ustring.match((d or ""),"(%a+)") or "-")])
end
if (not day) and ((purif(string.match(m or "","(%d+)") or "") or 32) <= (monthd[month] or 31)) then
msg = category.incomplete_parameters
day = purif(m:match("(%d+)") or "")
end
if not year then
msg = category.incomplete_parameters
year = purif(string.match(m or "","(%d+)") or "")
end
local dateout = {["year"]=year, ["month"]=month, ["day"]=day, ["msg"]=msg}
return dateout
end
local function glue(d1,m1,y1,d2,m2,y2)
if (not d1) and (not m1) and (not y1) and (not d2) and (not m2) and (not y2) then
return category.incomplete_parameters end
local gd,gm,gy,jd,jm,jy =
(d1 or ""),
(m1 or ""),
(y1 or ""),
(d2 or ""),
(m2 or ""),
(y2 or "")
--mw.log(tCon({gd,gm,gy,jd,jm,jy}))
local gm_sep = {" [["," год|","]]"}
if (not gy) or (gy == "") then gm_sep = {"","",""} end
return tCon({comment[1],trim(trim(jd .. " " .. jm) .. " " .. jy ),
comment[2]," ([[",trim(gd .. " " .. gm),"]]",gm_sep[1],(gy:match("(%d+)") or ""),
gm_sep[2],gy,gm_sep[3],")",category.incomplete_parameters})
end
-- добавить отображение без года
local function double_couple(jdate, gdate, wd, wm, wy, sq_brts, yearmark)
local msg = ""
msg = (jdate.msg or "") .. (gdate.msg or "")
local cd = {}
local jd = shallowcopy(jdate)
local gd = shallowcopy(gdate)
local left = "("
local right = ")"
if sq_brts then
left = "["
right = "]"
end
if (not isdate(jdate,true)) then return error((jdate.day or "") .. "." .. (jdate.month or "") .."." .. (jdate.year or "") .. " неподходящая дата")
elseif (not isdate(gdate)) then return error((gdate.day or "") .. "." .. (gdate.month or "") .."." .. (gdate.year or "") .. " неподходящая дата") end
if jd.year == gd.year then
cd.year = gd.year
gd.year, jd.year = nil, nil
end
if jd.month == gd.month then
cd.month = gd.month
gd.month, jd.month = nil, nil
end
if (not not cd.month) and wm then
return tCon({comment[1] .. trim(day2lang(jd,jdate,false) .. " " .. year2lang(jd.year,yearmark,false)) .. comment[2],
trim(left .. day2lang(gd,gdate,wd,wm) .. " " .. year2lang(gd.year,yearmark,wy)) .. right,
day2lang(cd,gdate,false) .. "]]", trim(year2lang(cd.year,yearmark,wy)..msg)}, " ")
end
return tCon({comment[1] .. trim(day2lang(jd,jdate,false) .. " " .. year2lang(jd.year,yearmark,false)) .. comment[2],
trim(left .. day2lang(gd,gdate,wd) .. " " .. year2lang(gd.year,yearmark,wy)) .. right,
trim(day2lang(cd,gdate,false)), trim(year2lang(cd.year,yearmark,wy)..msg)}, " ")
end
-- 40) Блок функций для перевода дат с использованием [[Юлианская дата]]
local function gri2jd( datein )
if not isdate(datein) then return error((datein.day or "") .. "." .. (datein.month or "") .."." .. (datein.year or "") .. " неподходящая дата") end
local year = datein.year
local month = datein.month
local day = datein.day
-- jd calculation
local a = math.floor((14 - month)/12)
local y = year + 4800 - a
local m = month + 12*a - 3
local offset = math.floor(y/4) - math.floor(y/100) + math.floor(y/400) - 32045
local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
-- jd validation
local low, high = -1931076.5, 5373557.49999
if not (low <= jd and jd <= high) then
return error((datein.day or "") .. "." .. (datein.month or "") .. "." .. (datein.year or "") .. " выходит за пределы разрешённого диапазона")
end
return jd
end
local function jd2jul( jd )
if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end
-- calendar date calculation
local c = jd + 32082
local d = math.floor((4*c + 3)/1461)
local e = c - math.floor(1461*d/4)
local m = math.floor((5*e + 2)/153)
local year_out = d - 4800 + math.floor(m/10)
local month_out = m + 3 - 12*math.floor(m/10)
local day_out = e - math.floor((153*m + 2)/5) + 1
-- output
local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
return dateout
end
local function jul2jd( datein )
if not isdate(datein,true) then return error((datein.day or "") .. "." .. (datein.month or "") ..".".. (datein.year or "") .. " неподходящая дата") end
local year = datein.year
local month = datein.month
local day = datein.day
-- jd calculation
local a = math.floor((14 - month)/12)
local y = year + 4800 - a
local m = month + 12*a - 3
local offset = math.floor(y/4) - 32083
local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
-- jd validation
local low, high = -1930999.5, 5373484.49999
if not (low <= jd and jd <= high) then
return error((datein.day or "") .. "." .. (datein.month or "") .."." .. (datein.year or "") .. " выходит за пределы разрешённого диапазона")
end
return jd
end
local function jd2gri( jd )
if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end
-- calendar date calculation
local a = jd + 32044
local b = math.floor((4*a + 3) / 146097)
local c = a - math.floor(146097*b/4)
local d = math.floor((4*c+3)/1461)
local e = c - math.floor(1461*d/4)
local m = math.floor((5*e+2)/153)
local day_out = e - math.floor((153*m+2)/5)+1
local month_out = m + 3 - 12*math.floor(m/10)
local year_out = 100*b + d - 4800 + math.floor(m/10)
-- output
local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
return dateout
end
local function astroyear(num, bc)
if not num then return error()
elseif type(num) ~= "number" then return error()
end
if num < 1 then return num end
if not bc then return num
else return 1 - num
end
end
local function recalc(datein,calend)
if inlist(calend,params[1]) then
return jd2jul(gri2jd(datein)), datein
elseif inlist(calend,params[2]) then
return datein, jd2gri(jul2jd(datein))
else error("Параметр " .. (calend or "") .. " не опознан, разрешённые: " .. tCon(params[1]," ") .. " и " .. tCon(params[2]," "))
end
end
-- 50) Функции для обработки UTC
local function utc(str,margin)
local d = 1
local dchar = "+"
local beginning = "[[UTC"
local ending = "]]"
local cat = ""
local nums = {}
local hmarg, timedec = 0, 0
local mmarg = "00"
local output = ""
-- checking type of input
if not margin then margin = 0
elseif type(tonumber(margin)) ~= 'number' then
output = "Can't shift by " .. margin
error(output)
end
if type(str) ~= 'string' then
error("Нет входящей строки")
elseif str:byte(1) == 43 then
elseif inbord(str:byte(1),48,57) then cat = "[[Категория:Википедия:Ошибка в часовом поясе НП]]"
elseif str:byte(1) == 45 or string.sub(str,1,3) == "−" or string.sub(str,1,1)=="-" then d = -1
else
error(string.char(str:byte(1)) .. " недопустимый первый символ")
end
-- parsing input
for num in string.gmatch(str,"(%d+)") do
table.insert(nums,purif(num))
end
if #nums > 2 then error("Ожидается всего 2 числа, а не " .. #nums)
elseif #nums == 0 then error("Необходимо что-то ввести")
elseif #nums == 1 then
if inbord(nums[1],0,14) then timedec = d*nums[1] + margin
else error("Только часы от -14 до 14") end
elseif #nums == 2 then
if not inbord(nums[1],0,14) then error("Только часы от -14 до 14")
elseif not inbord(nums[2],0,59) then error("Минуты только от 0 до 59")
else
timedec = d*(nums[1] + nums[2]/60) + margin
end
end
if tonumber(timedec) == purif(timedec) then hmarg = timedec
else
local h, m = math.modf(math.abs(timedec))
hmarg = h
mmarg = math.floor(m*60)
end
if timedec == 0 then
dchar = "±"
elseif timedec > 0 then
elseif timedec < 0 then
dchar = "−"
end
-- output
output = beginning .. dchar .. math.abs(hmarg) .. ":" .. string.format("%02d",mmarg) .. ending .. cat
return output
end
-- 60) Блок функций ввода-вывода
function p.NthDay( frame )
local args = getArgs(frame, { frameOnly = true })
local num, wday, mont, yea, format =
purif(args[1]), purif(args[2]), purif(args[3]), purif(args[4]), args[5]
if not format then format = "%d.%m.%y" end
if not inbord(num,-5,5) then
return error("The number must be between -5 and 5")
elseif num == 0 then
return error("The number must not be zero") end
if not inbord(wday,0,6) then
return error("The day of the week must be between 0 and 6") end
if not inbord(mont,1,12) then
return error("The month must be between 1 and 12") end
if not inbord(yea,0,9999) then
return error("Wrong year number") end
if inbord(num,1,5) then
local m_start = os.time{year=yea, month=mont, day=1, hour=0}
local m_wds = tonumber(os.date("%w", m_start))
local start_shift = (
(num - bool_to_number[wday >= m_wds]) * 7
- (m_wds - wday)
) * 24 * 60 * 60
local tim = m_start + start_shift
if tonumber(os.date("%m", tim)) == mont then
return (os.date(format, tim))
else
return (err)
end
elseif inbord(num,-5,-1) then
local m_end = os.time{year = yea, month = mont + 1, day = 1, hour = 0} - 24 * 60 * 60
local m_wde = tonumber(os.date("%w", m_end))
local end_shift = ((math.abs(num + 1) + bool_to_number[wday > m_wde]) * 7
+ (m_wde - wday)) * 24 * 60 * 60
local tim = m_end - end_shift
if tonumber(os.date("%m", tim)) == mont then
return (os.date(format, tim))
else
return (err)
end
end
end
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}})
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"1.2.1602"}})
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12.12.2021"}})
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"2021.12.12"}})
function p.ToIso( frame )
local args = getArgs(frame, { frameOnly = true })
local datein = args[1]
-- инициализация, заполнение обратных таблиц, копирование параметров
filling_months(mnlang, month_lang)
-- парсинг входящей даты по шаблону
local date = parse_date(datein)
if not (type(date.year) == 'number') then
return ("Wrong year: " .. unwarp(date))
end
if not (1 <= date.month and date.month <= 12) then
return ("Wrong month: " .. unwarp(date))
end
if not date.day or not (1 <= date.day and date.day <= month_end_day(date.month,date.year)) then
return ("Wrong day: " .. unwarp(date))
end
local timedate = os.time{year=date.year, month=date.month, day=date.day}
local date = os.date("%Y-%m-%d", timedate)
return date
end
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"1.2.1602"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"декабрь 2020"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12-2020"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12.12.2021"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"2021.12.12"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"2021.11"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"11.2021"}})
function p.BoxDate( frame )
local args = getArgs(frame, { frameOnly = true })
local txtDateIn, strFormat = args[1], args[2]
local txtDateOut, date, status = p.bxDate(txtDateIn, strFormat, params)
if status.brk then
return error(status.errorText)
else
return txtDateOut
end
end
function p.bxDate( txtDateIn , strFormat, params ) -- к отладке
local txtDateOut, date, status = "", {}, {brk = false, errorCat = "", errorText = ""}
strFormat = strFormat or "j xg Y"
-- заглушка - таблица параметров на будущее
params = params or {}
if not txtDateIn then
status.errorText = e.no_data
status.errorCat = category.no_parameters
status.brk = true
else
-- заполнение служебных таблиц
filling_months(mnlang, month_lang)
end
if not status.brk then
-- парсинг входящей даты по шаблону
date = parse_date(txtDateIn)
-- заменить сообщения об ошибках на списочные
if not (date.year and type(date.year) == 'number') then
status.errorText = string.format(e.box_date,txtDateIn)
status.errorCat = category.incomplete_parameters
status.brk = true
end
if not inbord(date.month,1,12) then
status.errorText = string.format(e.box_date,txtDateIn)
status.errorCat = category.incomplete_parameters
status.brk = true
end
if not date.day and string.find(strFormat,"[dDjlNwzW]") then
strFormat = trim(string.gsub(string.gsub(strFormat,"xg","F"),"[dDjlNwzW]",""))
elseif not date.day then
elseif not inbord(date.day,1,month_end_day(date.month,date.year)) then
status.errorText = string.format(e.box_date,txtDateIn)
status.errorCat = category.incomplete_parameters
status.brk = true
end
end
if not status.brk then
txtDateOut = mwlang:formatDate(strFormat,tCon({date.year,date.month,date.day},"-"),true)
end
return txtDateOut, date, status
end
function p.ToDate( frame ) -- возможно неиспользуемая
local args = getArgs(frame, { frameOnly = true })
local mwlang = mw.getContentLanguage()
local datein = args[1]
local format = "j xg Y"
if not string.match(datein, "%p") then return datein
elseif not args[2] then
else format = args[2]
end
return mwlang:formatDate(format,datein,true)
end
-- =p.unitime(mw.getCurrentFrame():newChild{title="smth",args={"−1:30","1"}})
function p.unitime( frame )
local args = getArgs(frame, { frameOnly = true })
local DST = 0
if not args[2] then
else DST = 1 end
local utcin = ""
local input = args[1]
if not input then return "" end
if inlist(input:upper(),tzs_names) then
utcin = known_tzs[input:upper()]
elseif (string.sub(input:upper(),1,3) == 'UTC') and (string.len(input) < 10) then
utcin = string.sub(input,4)
else
if string.sub(input,1,1) == '['
or string.sub(input,1,1) == '{'
or string.sub(input,1,1):upper() == 'U'
or string.sub(input,1,1):upper() == 'M' then
return input
-- elseif not string.find(string.upper(string.sub(input,1,1)),"[\65-\90]") or
-- not string.find(string.upper(string.sub(input,1,1)),"[\192-\223]") then
-- return input
else utcin = input end
end
-- elseif string.sub(input,1,3) ~= "−" then utcin = input
-- or not (not input:find("[А-я]")) при наличии в строке юникода не работает
local output = ""
if DST == 0 then output = utc(utcin)
else output = utc(utcin) .. ", [[летнее время|летом]] " .. utc(utcin,DST)
end
return output
end
-- УСТАРЕЛО
-- =p.OldDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020","ю",["bc"]="1",["wd"]="1",["wy"]="1",["sq_brts"]="1",["yearmark"]="г."}})
function p.OldDate( frame )
local args = getArgs(frame, { frameOnly = true })
if not args[1] then return err end
local gdate, jdate = {}, {}
local strin = args[1]
local cal = args[2]:lower() or "г"
local bc = is(args["bc"])
local wd = is(args["wd"])
local wm = is(args["wm"])
local wy = is(args["wy"])
if not wd then wm = false end
local sq_brts = is(args["sq_brts"])
local yearmark = "года"
if yesno(args["yearmark"]) then
elseif yesno(args["yearmark"]) == false then yearmark = ""
else yearmark = trim(args["yearmark"]) or "года" end
-- local infocard = is(args["infocard"])
-- local catName = args["catName"] or false
local datein = numstr2date(strin)
datein.year = astroyear(datein.year, bc)
jdate, gdate = recalc(datein,cal)
return double_couple(jdate, gdate, wd, wm, wy, sq_brts, yearmark)
end
-- =p.NewDate(mw.getCurrentFrame():newChild{title="Salt",args={"2020-02-20"}})
-- =p.NewDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020","ю",["bc"]="1",["wd"]="1",["wy"]="1",["sq_brts"]="1",["yearmark"]="г."}})
-- =p.NewDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020",["bc"]="0",["wd"]="1",["wy"]="1",["sq_brts"]="0",["yearmark"]=""}})
function p.NewDate( frame )
local args = getArgs(frame, { frameOnly = true })
if not args[1] then return err end
local strin = args[1]
local year, month, day
if not not strin:match( "(-?%d%d%d%d%d)-(%d%d)-(%d%d)" ) then
year, month, day = strin:match( "(-?%d%d%d%d%d)-(%d%d)-(%d%d)" )
elseif not not strin:match( "(-?%d+)-(%d+)-(%d+)" ) then
year, month, day = strin:match( "(-?%d+)-(%d+)-(%d+)" )
elseif not not strin:match( "(%d%d)%.(%d%d)%.(-?%d%d%d%d%d)" ) then
day, month, year = strin:match( "(%d%d)%.(%d%d)%.(-?%d%d%d%d%d)" )
elseif not not strin:match( "(%d+)%.(%d+)%.(-?%d+)" ) then
day, month, year = strin:match( "(%d+)%.(%d+)%.(-?%d+)" )
end
if not year then return error(args[1] .. " не подходит под форматы yyyy-mm-dd или dd.mm.yyyy")
end
local cal = "г"
if (not args[2]) or (args[2] == "") then cal = "г"
else cal = args[2]:lower() end
local bc,wd,wm,wy,sq_brts =
is(args["bc"]),
is(args["wd"]),
is(args["wd"]) and is(args["wm"]),
is(args["wy"]),
is(args["sq_brts"])
year = astroyear(purif(year),bc)
local datein = {["year"]=purif(year), ["month"]=purif(month), ["day"]=purif(day)}
local jdate, gdate = recalc(datein,cal)
local yearmark = "года"
local ym = args["yearmark"] or ""
if yesno(ym) then
elseif yesno(ym) == false then yearmark = ""
else
if not not ym:match("(%d+)") then
error("Цифры в обозначении года: " .. ym)
else yearmark = trim(ym) or "года" end
end
return double_couple(jdate, gdate, wd, wm, wy, sq_brts, yearmark)
end
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"3","июня",nil,"21","мая"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"28 августа","","1916 года","15"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"3","июня","1900","21","мая"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"6","июня","1889 год","25","мая"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"28","ноября","1917","15"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"28 августа","nil","1916 года","15"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"4","января","1915","22","декабря","1914 года"}})
-- {{OldStyleDate|день (НС)|месяц (НС)|год (НС)|день (СС)|месяц (СС)|год (СС)}}
function p.Test( frame )
local args = getArgs(frame, { frameOnly = true })
-- необходима проверка и замена nil на " "
--[[mw.log((args[1] or "") .. " " ..
(args[2] or "") .. " " ..
(args[3] or "") .. " " ..
(args[4] or "") .. " " ..
(args[5] or "") .. " " ..
(args[6] or "")) ]]--
local ingdate = triple_txt2date(args[1],args[2],args[3])
local injdate = triple_txt2date(args[4],args[5],args[6])
local j1date, g1date, j2date, g2date = init(4)
mw.log("ingdate-".. (undate(ingdate) or ""))
mw.log("injdate-".. (undate(injdate) or ""))
local bc,wd,wm,wy,sq_brts,ny =
is(args["bc"]),
is(args["wd"]),
is(args["wd"]) and is(args["wm"]),
is(args["wy"]),
is(args["sq_brts"]),
is(args["ny"])
-- подавление формата для локальных тестов
local wd, wm, wy = true, true, true
local yearmark = "года"
local ym = args["yearmark"] or ((mw.ustring.match((args[3] or ""),"(%a+)") or mw.ustring.match((args[6] or ""),"(%a+)")) or "")
-- mw.log("ym " .. ym)
if yesno(ym) then
elseif yesno(ym) == false then yearmark = ""
else
if not not ym:match("(%d+)") then
error("Цифры в обозначении года: " .. ym)
else yearmark = trim(ym) or "года" end
end
if isdate(ingdate) or isdate(injdate) then
if isdate(ingdate) then
j1date, g1date = recalc(ingdate,"g")
ingdate["full"] = true
end
if isdate(injdate) then
j2date, g2date = recalc(injdate,"j")
injdate["full"] = true
end
if ispartdate(ingdate) and ispartdate(injdate) then
mw.log("📏 " .. dmdist(ingdate,injdate))
mw.log("📏 " .. dmdist(j1date,g1date))
mw.log("📏 " .. dmdist(j2date,g2date))
mw.log("📏 " .. dmdist(ingdate,g1date))
mw.log("📏 " .. dmdist(injdate,j2date))
end
end
if ny then
if isyear(j1date) then
else j1date["year"] = "" end
if isyear(j2date) == nil then
else j2date["year"] = "" end
if isyear(g1date) == nil then
else g1date["year"] = "" end
if isyear(g2date) == nil then
else g2date["year"] = "" end
end
if (isdate(j1date) and isdate(g1date) and isdate(j2date) and isdate(g2date)) then
if ((j1date.year == j2date.year)
and (j1date.month == j2date.month)
and (j1date.day == j2date.day)) then
return double_couple(j1date, g1date, wd, wm, wy, sq_brts, yearmark)
else
mw.log("📏 " .. (tostring(dmdist(ingdate,injdate)) or ""))
return glue(args[1],args[2],args[3],args[4],args[5],args[6])
-- категория (предположительная разница в днях) и частичный вывод
end
elseif isdate(j1date) and isdate(g1date) then
return double_couple(j1date, g1date, wd, wm, wy, sq_brts, yearmark) -- категория плюс частичная проверка
elseif isdate(j2date) and isdate(g2date) then
return double_couple(j2date, g2date, wd, wm, wy, sq_brts, yearmark) -- категория плюс частичная проверка
elseif (ispartdate(ingdate) and ispartdate(injdate)) then
mw.log("ingdate ".. (undate(ingdate) or ""))
mw.log("injdate ".. (undate(injdate) or ""))
mw.log("j1date " .. (undate(j1date ) or ""))
mw.log("j2date " .. (undate(j2date ) or ""))
mw.log("g1date " .. (undate(g1date ) or ""))
mw.log("g2date " .. (undate(g2date ) or ""))
mw.log("📏 " .. (tostring(partdist(ingdate,injdate)) or "").. " — " .. (tostring(partdist(injdate,ingdate)) or ""))
return glue(args[1],args[2],args[3],args[4],args[5],args[6])
-- частичный или полный вывод, категория
else
mw.log("ingdate ".. (undate(ingdate) or ""))
mw.log("injdate ".. (undate(injdate) or ""))
mw.log("j1date " .. (undate(j1date ) or ""))
mw.log("j2date " .. (undate(j2date ) or ""))
mw.log("g1date " .. (undate(g1date ) or ""))
mw.log("g2date " .. (undate(g2date ) or ""))
return err .. category.incomplete_parameters
end
end
return p
a4a91f134ad3e3b246b3a6681a4ae438da766df4
Модуль:Message box/configuration
828
17
32
31
2025-01-25T21:00:10Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Message box configuration --
-- --
-- This module contains configuration data for [[Module:Message box]]. --
--------------------------------------------------------------------------------
return {
ambox = {
types = {
speedy = {
class = 'ambox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'ambox-delete',
image = 'Stop hand nuvola.svg'
},
content = {
class = 'ambox-content',
image = 'Emblem-important.svg'
},
style = {
class = 'ambox-style',
image = 'Broom_icon.svg'
},
move = {
class = 'ambox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'ambox-protection',
image = 'Padlock-silver-medium.svg'
},
notice = {
class = 'ambox-notice',
image = 'Information.svg'
},
good = {
class = 'ambox-good',
image = 'Green star boxed.svg'
},
serious = {
class = 'ambox-serious',
image = 'Stop hand nuvola.svg'
},
merge = {
class = 'ambox-merge',
image = 'Merge-split-transwiki default.svg'
},
discussion = {
class = 'ambox-discussion',
image = 'Nuvola apps ksirc.png'
}
},
default = 'notice',
allowBlankParams = {'talk', 'sect', 'date', 'issue', 'fix', 'subst', 'hidden', 'image'},
allowSmall = true,
smallParam = 'left',
smallClass = 'mbox-small-left',
substCheck = true,
classes = {'metadata', 'ambox'},
imageEmptyCell = true,
imageCheckBlank = true,
imageSmallSize = '20x20px',
imageCellDiv = true,
useCollapsibleTextFields = true,
imageRightNone = true,
sectionDefault = 'статья',
allowMainspaceCategories = true,
templateCategory = 'Шаблоны:Шаблоны-сообщения для статей',
templateCategoryRequireName = true,
templateErrorCategory = 'Шаблоны:Шаблоны-сообщения для статей с пропущенными параметрами',
templateErrorParamsToCheck = {'issue', 'fix'},
removalNotice = '[[Help:Maintenance template removal|Learn how and when to remove this template message]]',
templatestyles = 'Module:Message box/ambox.css',
},
cmbox = {
types = {
speedy = {
class = 'cmbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'cmbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'cmbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'cmbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'cmbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'cmbox-protection',
image = 'Padlock-silver-medium.svg'
},
notice = {
class = 'cmbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'cmbox'},
imageEmptyCell = true,
useCollapsibleTextFields = true,
templatestyles = 'Module:Message box/cmbox.css',
},
fmbox = {
types = {
warning = {
class = 'fmbox-warning',
image = 'Ambox warning pn.svg'
},
editnotice = {
class = 'fmbox-editnotice',
image = 'Information icon4.svg'
},
system = {
class = 'fmbox-system',
image = 'Information icon4.svg'
}
},
default = 'system',
showInvalidTypeError = true,
classes = {'fmbox'},
imageEmptyCell = false,
imageRightNone = false,
useCollapsibleTextFields = true,
templatestyles = 'Module:Message box/fmbox.css',
},
imbox = {
types = {
speedy = {
class = 'imbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'imbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'imbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'imbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'imbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'imbox-protection',
image = 'Padlock-silver-medium.svg'
},
license = {
class = 'imbox-license licensetpl',
image = 'Imbox license.png' -- @todo We need an SVG version of this
},
featured = {
class = 'imbox-featured',
image = 'Cscr-featured.svg'
},
notice = {
class = 'imbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'imbox'},
imageEmptyCell = true,
below = true,
useCollapsibleTextFields = true,
templateCategory = 'Шаблоны:Шаблоны-сообщения для файлов',
templatestyles = 'Module:Message box/imbox.css',
},
ombox = {
types = {
speedy = {
class = 'ombox-speedy',
image = 'OOjs UI icon alert-destructive.svg'
},
delete = {
class = 'ombox-delete',
image = 'OOjs UI icon alert-destructive.svg'
},
content = {
class = 'ombox-content',
image = 'OOjs UI icon notice-warning.svg'
},
style = {
class = 'ombox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'ombox-move',
image = 'Imbox move.png'
},
protection = {
class = 'ombox-protection',
image = 'Imbox protection.png'
},
notice = {
class = 'ombox-notice',
image = 'OOjs UI icon info-progressive.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'ombox'},
allowSmall = true,
imageEmptyCell = true,
imageRightNone = true,
useCollapsibleTextFields = true,
templatestyles = 'Module:Message box/ombox.css',
},
tmbox = {
types = {
speedy = {
class = 'tmbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'tmbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'tmbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'tmbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'tmbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'tmbox-protection',
image = 'Padlock-silver-medium.svg'
},
notice = {
class = 'tmbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'tmbox'},
allowSmall = true,
imageRightNone = true,
imageEmptyCell = true,
imageEmptyCellStyle = true,
useCollapsibleTextFields = true,
templateCategory = 'Шаблоны:Шаблоны-сообщения для страниц обсуждений',
templatestyles = 'Module:Message box/tmbox.css',
}
}
2c0750ec1561e8ec25c0988c411f3c69e4957483
Модуль:Category handler/data
828
18
34
33
2025-01-25T21:00:11Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- This module assembles data to be passed to [[Module:Category handler]] using
-- mw.loadData. This includes the configuration data and whether the current
-- page matches the title blacklist.
local data = require('Module:Category handler/config')
local mShared = require('Module:Category handler/shared')
local blacklist = require('Module:Category handler/blacklist')
local title = mw.title.getCurrentTitle()
data.currentTitleMatchesBlacklist = mShared.matchesBlacklist(
title.prefixedText,
blacklist
)
data.currentTitleNamespaceParameters = mShared.getNamespaceParameters(
title,
mShared.getParamMappings()
)
return data
abbc68048ff698e88dda06b64ecf384bbf583120
Модуль:Category handler/config
828
19
36
35
2025-01-25T21:00:11Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--------------------------------------------------------------------------------
-- [[Module:Category handler]] configuration data --
-- Language-specific parameter names and values can be set here. --
-- For blacklist config, see [[Module:Category handler/blacklist]]. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Start configuration data --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Parameter names --
-- These configuration items specify custom parameter names. --
-- To add one extra name, you can use this format: --
-- --
-- foo = 'parameter name', --
-- --
-- To add multiple names, you can use this format: --
-- --
-- foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'}, --
--------------------------------------------------------------------------------
cfg.parameters = {
-- The nocat and categories parameter suppress
-- categorisation. They are used with Module:Yesno, and work as follows:
--
-- cfg.nocat:
-- Result of yesno() Effect
-- true Categorisation is suppressed
-- false Categorisation is allowed, and
-- the blacklist check is skipped
-- nil Categorisation is allowed
--
-- cfg.categories:
-- Result of yesno() Effect
-- true Categorisation is allowed, and
-- the blacklist check is skipped
-- false Categorisation is suppressed
-- nil Categorisation is allowed
nocat = 'nocat',
categories = 'categories',
-- The parameter name for the legacy "category2" parameter. This skips the
-- blacklist if set to the cfg.category2Yes value, and suppresses
-- categorisation if present but equal to anything other than
-- cfg.category2Yes or cfg.category2Negative.
category2 = 'category2',
-- cfg.subpage is the parameter name to specify how to behave on subpages.
subpage = 'subpage',
-- The parameter for data to return in all namespaces.
all = 'all',
-- The parameter name for data to return if no data is specified for the
-- namespace that is detected.
other = 'other',
-- The parameter name used to specify a page other than the current page;
-- used for testing and demonstration.
demopage = 'page',
}
--------------------------------------------------------------------------------
-- Parameter values --
-- These are set values that can be used with certain parameters. Only one --
-- value can be specified, like this: --
-- --
-- cfg.foo = 'value name' -- --
--------------------------------------------------------------------------------
-- The following settings are used with the cfg.category2 parameter. Setting
-- cfg.category2 to cfg.category2Yes skips the blacklist, and if cfg.category2
-- is present but equal to anything other than cfg.category2Yes or
-- cfg.category2Negative then it supresses cateogrisation.
cfg.category2Yes = 'yes'
cfg.category2Negative = '¬'
-- The following settings are used with the cfg.subpage parameter.
-- cfg.subpageNo is the value to specify to not categorise on subpages;
-- cfg.subpageOnly is the value to specify to only categorise on subpages.
cfg.subpageNo = 'no'
cfg.subpageOnly = 'only'
--------------------------------------------------------------------------------
-- Default namespaces --
-- This is a table of namespaces to categorise by default. The keys are the --
-- namespace numbers. --
--------------------------------------------------------------------------------
cfg.defaultNamespaces = {
[ 0] = true, -- main
[ 6] = true, -- file
[ 12] = true, -- help
[ 14] = true, -- category
[100] = true, -- portal
[108] = true, -- book
}
--------------------------------------------------------------------------------
-- Wrappers --
-- This is a wrapper template or a list of wrapper templates to be passed to --
-- [[Module:Arguments]]. --
--------------------------------------------------------------------------------
cfg.wrappers = 'Template:Category handler'
--------------------------------------------------------------------------------
-- End configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line.
373cd107b13a5b00e6a1b7e66a749f12502c849d
Модуль:Category handler/shared
828
20
38
37
2025-01-25T21:00:12Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- This module contains shared functions used by [[Module:Category handler]]
-- and its submodules.
local p = {}
function p.matchesBlacklist(page, blacklist)
for i, pattern in ipairs(blacklist) do
local match = mw.ustring.match(page, pattern)
if match then
return true
end
end
return false
end
function p.getParamMappings(useLoadData)
local dataPage = 'Module:Namespace detect/data'
if useLoadData then
return mw.loadData(dataPage).mappings
else
return require(dataPage).mappings
end
end
function p.getNamespaceParameters(titleObj, mappings)
-- We don't use title.nsText for the namespace name because it adds
-- underscores.
local mappingsKey
if titleObj.isTalkPage then
mappingsKey = 'talk'
else
mappingsKey = mw.site.namespaces[titleObj.namespace].name
end
mappingsKey = mw.ustring.lower(mappingsKey)
return mappings[mappingsKey] or {}
end
return p
d2d5de1a031e6ce97c242cbfa8afe7a92cb9eca5
Модуль:Category handler/blacklist
828
21
40
39
2025-01-25T21:00:12Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- This module contains the blacklist used by [[Module:Category handler]].
-- Pages that match Lua patterns in this list will not be categorised unless
-- categorisation is explicitly requested.
return {
'^Main Page$', -- don't categorise the main page.
-- Don't categorise the following pages or their subpages.
-- "%f[/\0]" matches if the next character is "/" or the end of the string.
'^Wikipedia:Cascade%-protected items%f[/\0]',
'^User:UBX%f[/\0]', -- The userbox "template" space.
'^User talk:UBX%f[/\0]',
-- Don't categorise subpages of these pages, but allow
-- categorisation of the base page.
'^Wikipedia:Template messages/.*$',
'/[aA]rchive' -- Don't categorise archives.
}
c84948ad9808d5d323408d5d10d5652f748a0550
Модуль:Namespace detect/data
828
22
42
41
2025-01-25T21:00:13Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Namespace detect data --
-- This module holds data for [[Module:Namespace detect]] to be loaded per --
-- page, rather than per #invoke, for performance reasons. --
--------------------------------------------------------------------------------
local cfg = require('Module:Namespace detect/config')
local function addKey(t, key, defaultKey)
if key ~= defaultKey then
t[#t + 1] = key
end
end
-- Get a table of parameters to query for each default parameter name.
-- This allows wikis to customise parameter names in the cfg table while
-- ensuring that default parameter names will always work. The cfg table
-- values can be added as a string, or as an array of strings.
local defaultKeys = {
'main',
'talk',
'other',
'subjectns',
'demospace',
'demopage'
}
local argKeys = {}
for i, defaultKey in ipairs(defaultKeys) do
argKeys[defaultKey] = {defaultKey}
end
for defaultKey, t in pairs(argKeys) do
local cfgValue = cfg[defaultKey]
local cfgValueType = type(cfgValue)
if cfgValueType == 'string' then
addKey(t, cfgValue, defaultKey)
elseif cfgValueType == 'table' then
for i, key in ipairs(cfgValue) do
addKey(t, key, defaultKey)
end
end
cfg[defaultKey] = nil -- Free the cfg value as we don't need it any more.
end
local function getParamMappings()
--[[
-- Returns a table of how parameter names map to namespace names. The keys
-- are the actual namespace names, in lower case, and the values are the
-- possible parameter names for that namespace, also in lower case. The
-- table entries are structured like this:
-- {
-- [''] = {'main'},
-- ['wikipedia'] = {'wikipedia', 'project', 'wp'},
-- ...
-- }
--]]
local mappings = {}
local mainNsName = mw.site.subjectNamespaces[0].name
mainNsName = mw.ustring.lower(mainNsName)
mappings[mainNsName] = mw.clone(argKeys.main)
mappings['talk'] = mw.clone(argKeys.talk)
for nsid, ns in pairs(mw.site.subjectNamespaces) do
if nsid ~= 0 then -- Exclude main namespace.
local nsname = mw.ustring.lower(ns.name)
local canonicalName = mw.ustring.lower(ns.canonicalName)
mappings[nsname] = {nsname}
if canonicalName ~= nsname then
table.insert(mappings[nsname], canonicalName)
end
for _, alias in ipairs(ns.aliases) do
table.insert(mappings[nsname], mw.ustring.lower(alias))
end
end
end
return mappings
end
return {
argKeys = argKeys,
cfg = cfg,
mappings = getParamMappings()
}
d224f42a258bc308ef3ad8cc8686cd7a4f47d005
Модуль:Namespace detect/config
828
23
44
43
2025-01-25T21:00:13Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Namespace detect configuration data --
-- --
-- This module stores configuration data for Module:Namespace detect. Here --
-- you can localise the module to your wiki's language. --
-- --
-- To activate a configuration item, you need to uncomment it. This means --
-- that you need to remove the text "-- " at the start of the line. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Parameter names --
-- These configuration items specify custom parameter names. Values added --
-- here will work in addition to the default English parameter names. --
-- To add one extra name, you can use this format: --
-- --
-- cfg.foo = 'parameter name' --
-- --
-- To add multiple names, you can use this format: --
-- --
-- cfg.foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'} --
--------------------------------------------------------------------------------
---- This parameter displays content for the main namespace:
-- cfg.main = 'main'
---- This parameter displays in talk namespaces:
-- cfg.talk = 'talk'
---- This parameter displays content for "other" namespaces (namespaces for which
---- parameters have not been specified):
-- cfg.other = 'other'
---- This parameter makes talk pages behave as though they are the corresponding
---- subject namespace. Note that this parameter is used with [[Module:Yesno]].
---- Edit that module to change the default values of "yes", "no", etc.
-- cfg.subjectns = 'subjectns'
---- This parameter sets a demonstration namespace:
-- cfg.demospace = 'demospace'
---- This parameter sets a specific page to compare:
cfg.demopage = 'page'
--------------------------------------------------------------------------------
-- Table configuration --
-- These configuration items allow customisation of the "table" function, --
-- used to generate a table of possible parameters in the module --
-- documentation. --
--------------------------------------------------------------------------------
---- The header for the namespace column in the wikitable containing the list of
---- possible subject-space parameters.
-- cfg.wikitableNamespaceHeader = 'Namespace'
---- The header for the wikitable containing the list of possible subject-space
---- parameters.
-- cfg.wikitableAliasesHeader = 'Aliases'
--------------------------------------------------------------------------------
-- End of configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line.
0e4ff08d13c4b664d66b32c232deb129b77c1a56
Шаблон:Карточка
10
24
46
45
2025-01-25T21:00:14Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#if:{{{имя|}}}|{{#ifeq:{{{имя|}}}|-||{{#if:{{{цвет|}}}|{{#tag:templatestyles|
|wrapper=.infobox-{{#invoke:Hash|main|{{{имя}}} {{{вверху0|}}} {{{вверху|}}} {{{вверху2|}}}}}
|src=Шаблон:Цвет/{{{цвет|}}}.css
}}}}}}}}<table class="infobox infobox-{{#invoke:Hash|main|{{{имя}}} {{{вверху0|}}} {{{вверху|}}} {{{вверху2|}}}}} {{{класс_тела|}}}" style="{{{стиль_тела|}}}" {{#if:{{{имя|}}}|{{#ifeq:{{{имя|}}}|-||data-name="{{{имя}}}"}}}} {{#if:{{{from|}}}|{{#ifeq:{{{from|}}}|-||data-from="{{{from}}}"}}}}><!--
Вверху0
-->{{#if:{{{вверху0|}}}|<tr><td colspan="2" class="{{{класс_вверху0|}}}" style="text-align:center; {{{стиль_вверху0|}}}">{{{вверху0}}}</td></tr>}}<!--
Вверху
-->{{#if:{{{вверху|}}}|<tr><th colspan="2" scope="colgroup" class="infobox-above {{{класс_вверху|}}}" style="{{{стиль_вверху|}}}">{{{вверху}}}</th></tr>}}<!--
Вверху2
-->{{#if:{{{вверху2|}}}|<tr><td colspan="2" class="{{{класс_вверху2|}}}" style="text-align:center; {{{стиль_вверху2|}}}">{{{вверху2}}}</td></tr>}}<!--
Вверху3
-->{{#if:{{{вверху3|}}}|<tr><td colspan="2" class="{{{класс_вверху3|}}}" style="text-align:center; {{{стиль_вверху3|}}}">{{{вверху3}}}</td></tr>}}<!--
Изображение
-->{{#if:{{{изображение|}}}|<tr><td colspan="2" class="infobox-image {{{класс_изображения|}}}" style="{{{стиль_изображения|}}}"> {{{изображение}}} {{#if:{{{подпись|}}}|
<div class="media-caption" style="{{{стиль_подписи|}}}">{{{подпись}}}</div>}}</td></tr>}}<!--
Изображение2
-->{{#if:{{{изображение2|}}}|<tr><td colspan="2" class="infobox-image {{{класс_изображения2|}}}" style="{{{стиль_изображения2|}}}"> {{{изображение2}}} {{#if:{{{подпись2|}}}|
<div class="media-caption" style="{{{стиль_подписи2|}}}">{{{подпись2}}}</div>}}</td></tr>}}<!--
Изображение3
-->{{#if:{{{изображение3|}}}|<tr><td colspan="2" class="infobox-image {{{класс_изображения3|}}}" style="{{{стиль_изображения3|}}}"> {{{изображение3}}} {{#if:{{{подпись3|}}}|
<div class="media-caption" style="{{{стиль_подписи3|}}}">{{{подпись3}}}</div>}}</td></tr>}}<!--
Строки
-->{{#invoke:Infobox|renderLines}}<!--
Внизу
-->{{Карточка/внизу|
стиль_внизу_общий={{{стиль_внизу|}}}|
класс_внизу={{{класс_внизу|}}}|
внизу={{{внизу|}}}}}<!--
Внизу N
-->{{#invoke:Transclude|npc|Карточка/внизу|
стиль_внизу_общий={{{стиль_внизу|}}}|
стиль_внизу=|
класс_внизу=|
внизу=}}
</table><includeonly><!--
статьи
-->{{#if:{{NAMESPACE}}||<!--
-->{{#if:{{{имя|}}}||[[Категория:Статьи с шаблонами-карточками без имени]]}}<!--
-->{{#ifeq:{{{имя|}}}|{{subst:PAGENAME}}|[[Категория:Статьи с шаблонами-карточками без имени]]}}<!--
-->}}<!--
шаблоны
-->{{#ifeq:{{NAMESPACENUMBER}}|10|<!--
-->{{#if:{{{имя|}}}||[[Категория:Шаблоны-карточки без имени]]}}<!--
-->{{#ifeq:{{{имя|}}}|{{subst:PAGENAME}}|[[Категория:Шаблоны-карточки без имени]]}}<!--
-->{{#if:{{{название|}}}{{{стиль_названия|}}}|[[Категория:Шаблоны с использованием параметра «название» в шаблоне «Карточка»]]}}<!--
-->{{#if:{{{подпись|}}}{{{стиль_подписи|}}}{{{подпись2|}}}{{{стиль_подписи2|}}}{{{подпись3|}}}{{{стиль_подписи3|}}}|[[Категория:Шаблоны с использованием параметра «подпись» в шаблоне «Карточка»]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_тела|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_названия|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_вверху|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_вверху2|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_вверху3|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_подписи|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_подписи2|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_подписи3|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_заголовков|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_меток|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_текста|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifexpr:{{#invoke:Color_contrast|styleratio|{{{стиль_внизу|}}}}} < 4.5|[[Категория:Потенциально нечитаемые карточки]]}}<!--
-->{{#ifeq:{{{имя|}}}|{{PAGENAME}}|<!--
-->[[Категория:Шаблоны-карточки по алфавиту|{{ucfirst:{{без начала|{{PAGENAME}}|Карточка }}}}]]<!--
-->{{#if:{{{стиль_тела|}}}{{{стиль_вверху|}}}{{{стиль_заголовков|}}}{{{стиль_внизу|}}}|[[Категория:Википедия:Шаблоны-карточки с явным указанием стилей]]}}<!--
-->}}<!--
-->}}<!--
любое пространство имён
-->{{#if:{{{название|}}}{{{стиль_названия|}}}|[[Категория:Википедия:Страницы с использованием параметра «название» в шаблоне «Карточка»]]}}<!--
-->{{#if:{{{подпись|}}}{{{стиль_подписи|}}}{{{подпись2|}}}{{{стиль_подписи2|}}}{{{подпись3|}}}{{{стиль_подписи3|}}}|[[Категория:Википедия:Страницы с использованием параметра «подпись» в шаблоне «Карточка»]]}}</includeonly><noinclude>{{doc}}</noinclude>
5bd0cadc0cad51dc109de7db63622ab36743d386
Шаблон:Yesno
10
25
48
47
2025-01-25T21:00:14Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#switch: {{<includeonly>safesubst:</includeonly>lc: {{{1|¬}}} }}
|no
|n
|нет
|false
|0 = {{{no|<!-- null -->}}}
| = {{{blank|{{{no|<!-- null -->}}}}}}
|¬ = {{{¬|}}}
|yes
|y
|да
|true
|1 = {{{yes|yes}}}
|#default = {{{def|{{{yes|yes}}}}}}
}}<noinclude>
{{Documentation}}
</noinclude>
4e236854c477d07a225c2ab6c016c389b133e8d3
Шаблон:Wikidata
10
26
50
49
2025-01-25T21:00:14Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{#invoke:Wikidata|formatProperty|property={{{1|}}}|value={{{2|}}}}}</includeonly><noinclude>{{doc}}</noinclude>
9d3d422eca39504b018df6ec0bb047392a7aba7e
Шаблон:Карточка/Викисклад
10
27
52
51
2025-01-25T21:00:14Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{wikidata|p373|{{str rep|{{str rep|{{{1|}}}|Category:|}}|category:|}}|plain=false|text=Медиафайлы на Викискладе|icon={{{icon|}}}|icon_size={{{icon_size|}}}|from={{{from|}}}}}<!--
-->{{#if: {{{nocat|}}}{{NAMESPACE}} || <!--
-->{{#if: {{{1|}}} | [[Категория:Википедия:Ссылка на Викисклад непосредственно в статье]]<!--
-->{{#if: {{wikidata|p373|plain=true}}
| {{#ifeq: {{str rep|{{str rep|{{{1|}}}|Category:|}}|category:|}} | {{wikidata|p373|plain=true}} |[[Категория:Википедия:Ссылки на Викисклад в статье и на Викиданных совпадают]]| [[Категория:Википедия:Ссылки на Викисклад в статье и на Викиданных отличаются]] }}
| [[Категория:Википедия:Ссылка на Викисклад в статье, но не на Викиданных]]
}} }}<!--
--> }}<!--
-->{{#ifeq: {{NAMESPACE}} | Шаблон | {{#if: {{{2|}}} | [[Категория:Википедия:Шаблоны для низа карточек с лишним параметром]] }} }}<!--
--><noinclude>
{{doc}}
</noinclude>
40ef9a463c772ddbf54feae9e21d4037b692253e
Шаблон:Str rep
10
28
54
53
2025-01-25T21:00:15Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{{{{|safesubst:}}}#invoke:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|{{{4|1}}}}}</includeonly><noinclude>{{doc}}</noinclude>
c75032f150c372324c69a6f62ff4ab1492ad4cfa
Шаблон:Карточка/внизу
10
29
56
55
2025-01-25T21:00:15Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{#if:{{{внизу|}}}|<tr><td colspan="2" class="infobox-below {{{класс_внизу|}}}" style="{{{стиль_внизу_общий|}}};{{{стиль_внизу|}}}">{{{внизу|}}}</td></tr>}}</includeonly><noinclude>
{{doc}}
</noinclude>
169fb2d10b0847c2fd677eda9f159ba99025198f
Модуль:Wikidata
828
31
60
59
2025-01-25T21:00:16Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
---settings, may differ from project to project
local fileDefaultSize = '267x400px'
local outputReferences = true
local writingSystemElementId = 'Q8209'
local langElementId = 'Q7737'
---Ссылки на используемые модули, которые потребуются в 99% случаев загрузки страниц (чтобы иметь на виду при переименовании)
local moduleSources = require( 'Module:Sources' )
local WDS = require( 'Module:WikidataSelectors' )
---Константы
---@type string
local CONTENT_LANGUAGE_CODE = mw.language.getContentLanguage():getCode()
local p = {}
local g_config, g_frame
local formatDatavalue, formatEntityId, formatRefs, formatSnak, formatStatement,
formatStatementDefault, getSourcingCircumstances, getPropertyParams
---@param obj table
---@param target table
---@param skipEmpty boolean | nil
---@return table
local function copyTo( obj, target, skipEmpty )
for key, val in pairs( obj ) do
if skipEmpty ~= true or ( val ~= nil and val ~= '' ) then
target[ key ] = val
end
end
return target
end
---@param prev number | nil
---@param next number | nil
---@return number | nil
local function min( prev, next )
if prev == nil or prev > next then
return next
end
return prev
end
---@param prev number | nil
---@param next number | nil
---@return number | nil
local function max( prev, next )
if prev == nil or prev < next then
return next
end
return prev
end
---@param section string
---@param code string
---@return any | nil
local function getConfig( section, code )
if g_config == nil then
g_config = require( 'Module:Wikidata/config' )
end
if not g_config then
g_config = {}
end
if not section then
return g_config
end
if not code then
return g_config[ section ] or {}
end
if not g_config[ section ] then
return nil
end
return g_config[ section ][ code ]
end
---@param code string
---@param sortKey string | nil
---@return string
local function getCategoryByCode( code, sortKey )
local value = getConfig( 'categories', code )
if not value or value == '' then
return ''
end
if sortKey ~= nil then
return '[[Category:' .. value .. '|' .. sortKey .. ']]'; -- экранировать?
else
return '[[Category:' .. value .. ']]'
end
end
---@param isoStr string | table
---@return table | nil
local function splitISO8601( isoStr )
if 'table' == type( isoStr ) then
if isoStr.args and isoStr.args[ 1 ] then
isoStr = '' .. isoStr.args[ 1 ]
else
return 'unknown argument type: ' .. type( isoStr ) .. ': ' .. table.tostring( isoStr )
end
end
local Y, M, D = ( function( str )
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local _Y, _M, _D = mw.ustring.match( str, pattern )
return tonumber( _Y ), tonumber( _M ), tonumber( _D )
end )( isoStr )
local h, m, s = ( function( str )
local pattern = "T(%d+):(%d+):(%d+)%Z"
local _H, _M, _S = mw.ustring.match( str, pattern )
return tonumber( _H ), tonumber( _M ), tonumber( _S )
end )( isoStr )
local oh, om = ( function( str )
if str:sub(-1) == "Z" then -- ends with Z, Zulu time
return 0, 0
end
-- matches ±hh:mm, ±hhmm or ±hh; else returns nils
local pattern = "([-+])(%d%d):?(%d?%d?)$"
local sign, oh, om = mw.ustring.match( str, pattern )
sign, oh, om = sign or "+", oh or "00", om or "00"
return tonumber( sign .. oh ), tonumber( sign .. om )
end )( isoStr )
return { year=Y, month=M, day=D, hour=( h + oh ), min=( m + om ), sec=s }
end
---Внутренняя функции для получения границ временного диапазона
---@param time string
---@param precision number
---@return table | nil
function p._parseTimeBoundaries( time, precision )
local s = splitISO8601( time )
if not s then
return nil
end
if precision >= 0 and precision <= 8 then
local powers = { 1000000000 , 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10 }
local power = powers[ precision + 1 ]
local left = s.year - ( s.year % power )
return { tonumber( os.time( { year=left, month=1, day=1, hour=0, min=0, sec=0 } ) ) * 1000,
tonumber( os.time( { year=left + power - 1, month=12, day=31, hour=29, min=59, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 9 then
return { tonumber( os.time( { year=s.year, month=1, day=1, hour=0, min=0, sec=0} )) * 1000,
tonumber( os.time( { year=s.year, month=12, day=31, hour=23, min=59, sec=58} )) * 1000 + 1999 }
end
if precision == 10 then
local lastDays = { 31, 28.25, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
local lastDay = lastDays[ s.month ]
return { tonumber( os.time( { year=s.year, month=s.month, day=1, hour=0, min=0, sec=0 } ) ) * 1000,
tonumber( os.time( { year=s.year, month=s.month, day=lastDay, hour=23, min=59, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 11 then
return { tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=0, min=0, sec=0 } ) ) * 1000,
tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=23, min=59, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 12 then
return { tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=0, sec=0 } ) ) * 1000,
tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=59, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 13 then
return { tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=s.min, sec=0 } ) ) * 1000,
tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=s.min, sec=58 } ) ) * 1000 + 1999 }
end
if precision == 14 then
local t = tonumber( os.time( { year=s.year, month=s.month, day=s.day, hour=s.hour, min=s.min, sec=0 } ) )
return { t * 1000, t * 1000 + 999 }
end
error( 'Unsupported precision: ' .. precision )
end
---Внутренняя функция для получения числового значения времени из snak'а
---@param table snak
---@return number | nil
function p._parseTimeFromSnak( snak )
if snak and snak.datavalue and snak.datavalue.value and snak.datavalue.value.time then
local timeData = splitISO8601( tostring( snak.datavalue.value.time ) )
timeData.month = math.max( timeData.month, 1 )
timeData.day = math.max( timeData.day, 1 )
return tonumber( os.time( timeData ) ) * 1000
end
return nil
end
---Функция для формирования категории на основе wikidata/config
---@param options table
---@param entityId string
---@return string
local function extractCategory( options, entityId )
if not entityId or not options.category or options.nocat then
return ''
end
if type( entityId ) ~= 'string' then
entityId = entityId.id
end
local claims = WDS.load( entityId, options.category )
if not claims then
return ''
end
for _, claim in pairs( claims ) do
if claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.type == 'wikibase-entityid'
then
local catEntityId = claim.mainsnak.datavalue.value.id
local wbStatus, catSiteLink = pcall( mw.wikibase.getSitelink, catEntityId )
if wbStatus and catSiteLink then
return '[[' .. catSiteLink .. ']]'
end
end
end
return ''
end
---Преобразует строку в булевое значение
---@param valueToParse string
---@return boolean Преобразованное значение, если его удалось распознать, или defaultValue во всех остальных случаях
local function toBoolean( valueToParse, defaultValue )
if valueToParse ~= nil then
if valueToParse == false or valueToParse == '' or valueToParse == 'false' or valueToParse == '0' then
return false
end
return true
end
return defaultValue
end
---Обрачивает отформатированное значение в инлайновый или блочный тег.
---@param value string value
---@param attributes table of attributes
---@return string HTML tag with value
local function wrapValue( value, attributes )
local tagName = 'span'
local spacer = ''
if string.match( value, '\n' )
or string.match( value, '<t[dhr][ >]' )
or string.match( value, '<div[ >]' )
or string.find( value, 'UNIQ%-%-imagemap' )
then
tagName = 'div'
spacer = '\n'
end
local attrString = ''
for key, val in pairs( attributes or {} ) do
local _key = mw.text.trim( key )
local _value = mw.text.encode( mw.text.trim( val ) )
attrString = attrString .. _key .. '="' .. _value .. '" '
end
return '<' .. tagName .. ' ' .. attrString .. '>' .. spacer .. value .. '</' .. tagName .. '>'
end
---Wraps formatted snak value into HTML tag with attributes.
---@param value string value of snak
---@param hash string
---@param attributes table of extra attributes
---@return string HTML tag with value
local function wrapSnak( value, hash, attributes )
local newAttributes = mw.clone( attributes or {} )
newAttributes[ 'class' ] = ( newAttributes[ 'class' ] or '' ) .. ' wikidata-snak'
if hash then
newAttributes[ 'data-wikidata-hash'] = hash
else
newAttributes[ 'class' ] = newAttributes[ 'class' ] .. ' wikidata-main-snak'
end
return wrapValue( value, newAttributes )
end
---Wraps formatted statement value into HTML tag with attributes.
---@param value string value of statement
---@param propertyId string PID of property
---@param claimId string ID of claim or nil for local value
---@param attributes table of extra attributes
---@return string HTML tag with value
local function wrapStatement( value, propertyId, claimId, attributes )
local newAttributes = mw.clone( attributes or {} )
newAttributes[ 'class' ] = newAttributes[ 'class' ] or ''
newAttributes[ 'data-wikidata-property-id' ] = string.upper( propertyId )
if claimId then
newAttributes[ 'class' ] = newAttributes[ 'class' ] .. ' wikidata-claim'
newAttributes[ 'data-wikidata-claim-id' ] = claimId
else
newAttributes[ 'class' ] = newAttributes[ 'class' ] .. ' no-wikidata'
end
return wrapValue( value, newAttributes )
end
---Wraps formatted qualifier's statement value into HTML tag with attributes.
---@param value string value of qualifier's statement
---@param qualifierId string PID of qualifier
---@param attributes table of extra attributes
---@return string HTML tag with value
local function wrapQualifier( value, qualifierId, attributes )
local newAttributes = mw.clone( attributes or {} )
newAttributes[ 'data-wikidata-qualifier-id' ] = string.upper( qualifierId )
return wrapValue( value, newAttributes )
end
---Функция для получения сущности (еntity) для текущей страницы
---Подробнее о сущностях см. d:Wikidata:Glossary/ru
---@param id string Идентификатор (типа P18, Q42)
---@return table Таблица, элементы которой индексируются с нуля
local function getEntityFromId( id )
local entity
local wbStatus
if id then
wbStatus, entity = pcall( mw.wikibase.getEntity, id )
else
wbStatus, entity = pcall( mw.wikibase.getEntity )
end
return entity
end
---Внутренняя функция для формирования сообщения об ошибке
---@param key string Ключ элемента в таблице config.errors (например entity-not-found)
---@return void
local function throwError( key )
error( getConfig( 'errors', key ) )
end
---Функция для получения идентификатора сущностей
---@param value table
---@return string
local function getEntityIdFromValue( value )
local prefix = ''
if value[ 'entity-type' ] == 'item' then
prefix = 'Q'
elseif value[ 'entity-type' ] == 'property' then
prefix = 'P'
else
throwError( 'unknown-entity-type' )
end
return prefix .. value[ 'numeric-id' ]
end
---Проверка на наличие специализированной функции в опциях
---@param options table
---@param prefix string
---@return function
local function getUserFunction( options, prefix, defaultFunction )
-- проверка на указание специализированных обработчиков в параметрах,
-- переданных при вызове
if options[ prefix .. '-module' ] or options[ prefix .. '-function' ] then
-- проверка на пустые строки в параметрах или их отсутствие
if not options[ prefix .. '-module' ] or not options[ prefix .. '-function' ] then
throwError( 'unknown-' .. prefix .. '-module' )
end
-- динамическая загруза модуля с обработчиком указанным в параметре
local formatter = require( 'Module:' .. options[ prefix .. '-module' ] )
if formatter == nil then
throwError( prefix .. '-module-not-found' )
end
local fun = formatter[ options[ prefix .. '-function' ] ]
if fun == nil then
throwError( prefix .. '-function-not-found' )
end
return fun
end
return defaultFunction
end
---Выбирает свойства по property id, дополнительно фильтруя их по рангу
---@param context table
---@param options table
---@param propertySelector string
---@return table | nil
local function selectClaims( context, options, propertySelector )
if not context then error( 'context not specified' ); end
if not options then error( 'options not specified' ); end
if not options.entityId then error( 'options.entity is missing' ); end
if not propertySelector then error( 'propertySelector not specified' ); end
local result = WDS.load( options.entityId, propertySelector )
if not result or #result == 0 then
return nil
end
if options.limit and options.limit ~= '' and options.limit ~= '-' then
local limit = tonumber( options.limit, 10 )
while #result > limit do
table.remove( result )
end
end
return result
end
---Функция для получения значения свойства элемента в заданный момент времени.
---@param entityId string
---@param boundaries table Временные границы
---@param propertyIds table<string>
---@param selectors table<string>
---@return table Таблица соответствующих значений свойства
local function getPropertyInBoundaries( context, entityId, boundaries, propertyIds, selectors )
if type( entityId ) ~= 'string' then error( 'type of entityId argument expected string, but was ' .. type(entityId)); end
local results = {}
if not propertyIds or #propertyIds == 0 then
return results
end
for i, propertyId in ipairs( propertyIds ) do
local selector
if selectors ~= nil then
selector = selectors[ i ] or selectors[ propertyId ] or propertyId
else
selector = propertyId
end
local fakeAllClaims = {}
fakeAllClaims[ propertyId ] = mw.wikibase.getAllStatements( entityId, propertyId )
local filteredClaims = WDS.filter( fakeAllClaims, selector .. '[rank:preferred, rank:normal]' )
if filteredClaims then
for _, claim in pairs( filteredClaims ) do
if not boundaries then
if not claim.qualifiers or not claim.qualifiers.P582 then
table.insert( results, claim.mainsnak )
end
else
local startBoundaries = p.getTimeBoundariesFromQualifier( context.frame, context, claim, 'P580' )
local endBoundaries = p.getTimeBoundariesFromQualifier( context.frame, context, claim, 'P582' )
if ( startBoundaries == nil or startBoundaries[ 1 ] <= boundaries[ 1 ] ) and
( endBoundaries == nil or endBoundaries[ 1 ] >= boundaries[ 2 ] )
then
table.insert( results, claim.mainsnak )
end
end
end
end
if #results > 0 then
break
end
end
return results
end
---@param context table
---@param propertyId string
---@return table | nil
function p.getTimeBoundariesFromProperty( context, propertyId )
local dateClaims = WDS.filter( context.entity.claims, propertyId )
if not dateClaims or #dateClaims == 0 then
return nil;
end
-- only support exact date so far, but need improvment
local left = nil
local right = nil
for _, claim in pairs( dateClaims ) do
if not claim.mainsnak then
return nil
end
local boundaries = context.parseTimeBoundariesFromSnak( claim.mainsnak )
if not boundaries then
return nil
end
left = min( left, boundaries[ 1 ] )
right = max( right, boundaries[ 2 ] )
end
if not left or not right then
return nil
end
return { left, right }
end
---@param context table
---@param propertyIds table<string>
---@return table | nil
function p.getTimeBoundariesFromProperties( context, propertyIds )
for _, propertyId in ipairs( propertyIds ) do
local result = p.getTimeBoundariesFromProperty( context, propertyId );
if result then
return result
end
end
return nil
end
---@param context table
---@param statement table
---@param qualifierId string
---@return table | nil
function p.getTimeBoundariesFromQualifier( _, context, statement, qualifierId )
-- only support exact date so far, but need improvement
local left, right
if statement.qualifiers and statement.qualifiers[ qualifierId ] then
for _, qualifier in pairs( statement.qualifiers[ qualifierId ] ) do
local boundaries = context.parseTimeBoundariesFromSnak( qualifier )
if not boundaries then
return nil
end
left = min( left, boundaries[ 1 ] )
right = max( right, boundaries[ 2 ] )
end
end
if not left or not right then
return nil
end
return { left, right }
end
---@param _ table
---@param context table
---@param statement table
---@param qualifierIds table<string>
---@return table | nil
function p.getTimeBoundariesFromQualifiers( _, context, statement, qualifierIds )
if not qualifierIds then
qualifierIds = { 'P582', 'P580', 'P585' }
end
for _, qualifierId in pairs( qualifierIds ) do
local result = p.getTimeBoundariesFromQualifier( _, context, statement, qualifierId )
if result then
return result
end
end
return nil
end
---@type table<string>
local getLabelWithLang_DEFAULT_PROPERTIES = { 'P1813', 'P1448', 'P1705' }
---@type table<string>
local getLabelWithLang_DEFAULT_SELECTORS = {
'P1813[language:' .. CONTENT_LANGUAGE_CODE .. '][!P282,P282:' .. writingSystemElementId .. '][!P3831,P3831:Q105690470]',
'P1448[language:' .. CONTENT_LANGUAGE_CODE .. '][!P282,P282:' .. writingSystemElementId .. '][!P3831,P3831:Q105690470]',
'P1705[language:' .. CONTENT_LANGUAGE_CODE .. '][!P282,P282:' .. writingSystemElementId .. '][!P3831,P3831:Q105690470]'
}
---Функция для получения метки элемента в заданный момент времени.
---@param context table
---@param options table
---@param entityId string
---@param boundaries table
---@param propertyIds table
---@param selectors table<string>
---@return string, string Текстовая метка элемента, язык метки
local function getLabelWithLang( context, options, entityId, boundaries, propertyIds, selectors )
if type( entityId ) ~= 'string' then error( 'type of entityId argument expected string, but was ' .. type( entityId ) ); end
if not entityId then
return nil
end
local langCode = CONTENT_LANGUAGE_CODE
-- name from label
local label
if options.text and options.text ~= '' then
label = options.text
else
if not propertyIds then
propertyIds = getLabelWithLang_DEFAULT_PROPERTIES
selectors = getLabelWithLang_DEFAULT_SELECTORS
end
-- name from properties
local results = getPropertyInBoundaries( context, entityId, boundaries, propertyIds, selectors )
for _, result in pairs( results ) do
if result.datavalue and result.datavalue.value then
if result.datavalue.type == 'monolingualtext' and result.datavalue.value.text then
label = result.datavalue.value.text
langCode = result.datavalue.value.language
break
elseif result.datavalue.type == 'string' then
label = result.datavalue.value
break
end
end
end
if not label then
label, langCode = mw.wikibase.getLabelWithLang( entityId )
if not langCode then
return nil
end
end
end
return label, langCode
end
---@param context table
---@param options table
---@return string
local function formatPropertyDefault( context, options )
if not context then error( 'context not specified' ); end
if not options then error( 'options not specified' ); end
if not options.entityId then error( 'options.entityId missing' ); end
local claims
if options.property then -- TODO: Почему тут может не быть property?
if options.rank then -- передать настройки ранга из конфига
claims = context.selectClaims( options, options.property .. options.rank )
else
claims = context.selectClaims( options, options.property )
end
end
if claims == nil then
return '' --TODO error?
end
-- Обход всех заявлений утверждения и с накоплением оформленных предпочтительных
-- заявлений в таблице
local formattedClaims = {}
for _, claim in pairs( claims ) do
local formattedStatement = context.formatStatement( options, claim )
-- здесь может вернуться либо оформленный текст заявления, либо строка ошибки, либо nil
if formattedStatement and formattedStatement ~= '' then
if not options.plain then
formattedStatement = context.wrapStatement( formattedStatement, options.property, claim.id )
end
table.insert( formattedClaims, formattedStatement )
end
end
-- создание текстовой строки со списком оформленых заявлений из таблицы
local out = mw.text.listToText( formattedClaims, options.separator, options.conjunction )
if out ~= '' then
if options.before then
out = options.before .. out
end
if options.after then
out = out .. options.after
end
end
return out
end
---Create context
---@param initOptions table
---@return table | nil
local function initContext( initOptions )
local context = {
entityId = initOptions.entityId,
entity = initOptions.entity,
extractCategory = extractCategory,
formatSnak = formatSnak,
formatPropertyDefault = formatPropertyDefault,
formatStatementDefault = formatStatementDefault,
getPropertyInBoundaries = getPropertyInBoundaries,
getTimeBoundariesFromProperty = p.getTimeBoundariesFromProperty,
getTimeBoundariesFromProperties = p.getTimeBoundariesFromProperties,
getTimeBoundariesFromQualifier = p.getTimeBoundariesFromQualifier,
getTimeBoundariesFromQualifiers = p.getTimeBoundariesFromQualifiers,
parseTimeFromSnak = p._parseTimeFromSnak,
getLabelWithLang = getLabelWithLang,
wrapSnak = wrapSnak,
wrapStatement = wrapStatement,
wrapQualifier = wrapQualifier,
}
context.cloneOptions = function( options )
local entity = options.entity
options.entity = nil
local newOptions = mw.clone( options )
options.entity = entity
newOptions.entity = entity
newOptions.frame = options.frame; -- На склонированном фрейме frame:expandTemplate()
return newOptions
end
context.formatProperty = function( options )
local func = getUserFunction( options, 'property', context.formatPropertyDefault )
return func( context, options )
end
context.formatStatement = function( options, statement ) return formatStatement( context, options, statement ) end
context.formatSnak = function( options, snak, circumstances ) return formatSnak( context, options, snak, circumstances ) end
context.formatRefs = function( options, statement ) return formatRefs( context, options, statement ) end
context.parseTimeBoundariesFromSnak = function( snak )
if snak and snak.datavalue and snak.datavalue.value and snak.datavalue.value.time and snak.datavalue.value.precision then
return p._parseTimeBoundaries( snak.datavalue.value.time, snak.datavalue.value.precision )
end
return nil
end
context.getSourcingCircumstances = function( statement )
return getSourcingCircumstances( statement )
end
context.selectClaims = function( options, propertyId )
return selectClaims( context, options, propertyId )
end
return context
end
---Функция для оформления утверждений (statement)
---Подробнее о утверждениях см. d:Wikidata:Glossary/ru
---@param options table
---@return string Formatted wikitext.
local function formatProperty( options )
-- Получение сущности по идентификатору
local entity = getEntityFromId( options.entityId )
if not entity then
return -- throwError( 'entity-not-found' )
end
-- проверка на присутсвие у сущности заявлений (claim)
-- подробнее о заявлениях см. d:Викиданные:Глоссарий
if not entity.claims then
return '' --TODO error?
end
-- improve options
options.frame = g_frame
options.entity = entity
options.extends = function( self, newOptions )
return copyTo( newOptions, copyTo( self, {} ) )
end
if options.i18n then
options.i18n = copyTo( options.i18n, copyTo( getConfig( 'i18n' ), {} ) )
else
options.i18n = getConfig( 'i18n' )
end
local context = initContext( options )
return context.formatProperty( options )
end
---Функция для оформления одного утверждения (statement)
---@param context table
---@param options table
---@param statement table
---@return string Formatted wikitext.
function formatStatement( context, options, statement )
if not statement then
error( 'statement is not specified or nil' )
end
if not statement.type or statement.type ~= 'statement' then
throwError( 'unknown-claim-type' )
end
local functionToCall = getUserFunction( options, 'claim', context.formatStatementDefault )
return functionToCall( context, options, statement )
end
---@param statement table
---@return table
function getSourcingCircumstances( statement )
if not statement then
error( 'statement is not specified' )
end
local circumstances = {}
if statement.qualifiers and statement.qualifiers.P1480 then
for _, qualifier in pairs( statement.qualifiers.P1480 ) do
if qualifier
and qualifier.datavalue
and qualifier.datavalue.type == 'wikibase-entityid'
and qualifier.datavalue.value
and qualifier.datavalue.value[ 'entity-type'] == 'item'
then
table.insert( circumstances, qualifier.datavalue.value.id )
end
end
end
return circumstances
end
---Функция для оформления одного утверждения (statement)
---@param context table Context.
---@param options table Parameters.
---@param statement table
---@return string Formatted wikitext.
function formatStatementDefault( context, options, statement )
if not context then error( 'context is not specified' ) end
if not options then error( 'options is not specified' ) end
if not statement then error( 'statement is not specified' ) end
local circumstances = context.getSourcingCircumstances( statement )
options.qualifiers = statement.qualifiers
local result = context.formatSnak( options, statement.mainsnak, circumstances )
if options.qualifier and statement.qualifiers and statement.qualifiers[ options.qualifier ] then
local qualifierConfig = getPropertyParams( options.qualifier, nil, {} )
if options.i18n then
qualifierConfig.i18n = options.i18n
end
if qualifierConfig.datatype == 'time' then
qualifierConfig.nolinks = true
end
local qualifierValues = {}
for _, qualifierSnak in pairs( statement.qualifiers[ options.qualifier ] ) do
local snakValue = context.formatSnak( qualifierConfig, qualifierSnak )
if snakValue and snakValue ~= '' then
table.insert( qualifierValues, snakValue )
end
end
if result and result ~= '' and #qualifierValues then
if qualifierConfig.invisible then
result = result .. table.concat( qualifierValues, ', ' )
else
result = result .. ' (' .. table.concat( qualifierValues, ', ' ) .. ')'
end
end
end
if result and result ~= '' and options.references then
result = result .. context.formatRefs( options, statement )
end
return result
end
---Функция для оформления части утверждения (snak)
---Подробнее о snak см. d:Викиданные:Глоссарий
---@param context table Context.
---@param options table Parameters.
---@param snak table
---@param circumstances table
---@return string Formatted wikitext.
function formatSnak( context, options, snak, circumstances )
circumstances = circumstances or {}
local result
if snak.snaktype == 'somevalue' then
if options[ 'somevalue' ] and options[ 'somevalue' ] ~= '' then
result = options[ 'somevalue' ]
else
result = options.i18n[ 'somevalue' ]
end
elseif snak.snaktype == 'novalue' then
if options[ 'novalue' ] and options[ 'novalue' ] ~= '' then
result = options[ 'novalue' ]
else
result = options.i18n[ 'novalue' ]
end
elseif snak.snaktype == 'value' then
result = formatDatavalue( context, options, snak.datavalue, snak.datatype )
for _, item in pairs( circumstances ) do
if options.i18n[ item ] then
result = options.i18n[ item ] .. result
end
end
else
throwError( 'unknown-snak-type' )
end
if not result or result == '' then
return nil
end
if options.plain then
return result
end
return context.wrapSnak( result, snak.hash )
end
---Функция для оформления объектов-значений с географическими координатами
---@param value string Raw value.
---@param options table Parameters.
---@return string Formatted string.
local function formatGlobeCoordinate( value, options )
-- проверка на требование в параметрах вызова на возврат сырого значения
if options[ 'subvalue' ] == 'latitude' then -- широты
return value[ 'latitude' ]
elseif options[ 'subvalue' ] == 'longitude' then -- долготы
return value[ 'longitude' ]
elseif options[ 'nocoord' ] and options[ 'nocoord' ] ~= '' then
-- если передан параметр nocoord, то не выводить координаты
-- обычно это делается при использовании нескольких карточек на странице
return ''
else
-- в противном случае формируются параметры для вызова шаблона {{coord}}
-- нужно дописать в документации шаблона, что он отсюда вызывается, и что
-- любое изменние его парамеров должно быть согласовано с кодом тут
local coordModule = require( 'Module:Coordinates' )
local globe = options.globe or ''
if globe == '' and value[ 'globe' ] then
local globes = require( 'Module:Wikidata/Globes' )
globe = globes[ value[ 'globe' ] ] or ''
end
local display = 'inline'
if options.display and options.display ~= '' then
display = options.display
elseif ( options.property:upper() == 'P625' ) then
display = 'title'
end
local format = options.format or ''
if format == '' then
format = 'dms'
if value[ 'precision' ] then
local precision = value[ 'precision' ] * 60
if precision >= 60 then
format = 'd'
elseif precision >= 1 then
format = 'dm'
end
end
end
g_frame.args = {
tostring( value[ 'latitude' ] ),
tostring( value[ 'longitude' ] ),
globe = globe,
type = options.type and options.type or '',
scale = options.scale and options.scale or '',
display = display,
format = format,
}
return coordModule.coord(g_frame)
end
end
---Функция для оформления объектов-значений с файлами с Викисклада
---@param value string Raw value.
---@param options table Parameters.
---@return string Formatted string.
local function formatCommonsMedia( value, options )
local image = value
local caption = ''
if options[ 'caption' ] and options[ 'caption' ] ~= '' then
caption = options[ 'caption' ]
end
if caption ~= '' then
caption = wrapQualifier( caption, 'P2096', { class = 'media-caption', style = 'display:block' } )
end
if not string.find( value, '[%[%]%{%}]' ) and not string.find( value, 'UNIQ%-%-imagemap' ) then
-- если в value не содержится викикод или imagemap, то викифицируем имя файла
-- ищем слово imagemap в строке, потому что вставляется плейсхолдер: [[phab:T28213]]
image = '[[File:' .. value .. '|frameless'
if options[ 'border' ] and options[ 'border' ] ~= '' then
image = image .. '|border'
end
local size = options[ 'size' ]
if size and size ~= '' then
-- TODO: check localized pixel names too
if not string.match( size, 'px$' ) then
size = size .. 'px'
end
else
size = fileDefaultSize
end
image = image .. '|' .. size
if options[ 'alt' ] and options[ 'alt' ] ~= '' then
image = image .. '|alt=' .. options[ 'alt' ]
end
if caption ~= '' then
image = image .. '|' .. caption
end
image = image .. ']]'
if caption ~= '' then
image = image .. '<br>' .. caption
end
else
image = image .. caption .. getCategoryByCode( 'media-contains-markup' )
end
return image
end
---Function for render math formulas
---@param value string Value.
---@param options table Parameters.
---@return string Formatted string.
local function formatMath( value, options )
return options.frame:extensionTag{ name = 'math', content = value }
end
---Функция для оформления внешних идентификаторов
---@param value string
---@param options table
---@return string
local function formatExternalId( value, options )
local formatter = options.formatter
local propertyId = options.property:upper()
if not formatter or formatter == '' then
local isGoodFormat = false
local wbStatus, formatRegexStatements = pcall( mw.wikibase.getBestStatements, propertyId, 'P1793' )
if wbStatus and formatRegexStatements then
for _, statement in pairs( formatRegexStatements ) do
if statement.mainsnak.snaktype == 'value' then
local pattern = mw.ustring.gsub( statement.mainsnak.datavalue.value, '\\', '%' )
pattern = mw.ustring.gsub( pattern, '{%d+,?%d*}', '+' )
if ( string.find( pattern, '|' ) or string.find( pattern, '%)%?' )
or mw.ustring.match( value, '^' .. pattern .. '$' ) ~= nil ) then
isGoodFormat = true
break
end
end
end
end
if isGoodFormat then
local formatterStatements
wbStatus, formatterStatements = pcall( mw.wikibase.getBestStatements, propertyId, 'P1630' )
if wbStatus and formatterStatements then
for _, statement in pairs( formatterStatements ) do
if statement.mainsnak.snaktype == 'value' then
formatter = statement.mainsnak.datavalue.value
break
end
end
end
end
end
if formatter and formatter ~= '' then
local encodedValue = mw.ustring.gsub( value, '%%', '%%%%' ) -- ломается, если подставить внутрь другого mw.ustring.gsub
local link = mw.ustring.gsub(
mw.ustring.gsub( formatter, '$1', encodedValue ), '.',
{ [ ' ' ] = '%20', [ '+' ] = '%2b', [ '[' ] = '%5B', [ ']' ] = '%5D' } )
local title = options.title
if not title or title == '' then
title = '$1'
end
title = mw.ustring.gsub(
mw.ustring.gsub( title, '$1', encodedValue ), '.',
{ [ '[' ] = '(', [ ']' ] = ')' } )
return '[' .. link .. ' ' .. title .. ']'
end
return value
end
---Функция для оформления числовых значений
---@param value table Объект-значение
---@param options table Таблица параметров
---@return string Оформленный текст
local function formatQuantity( value, options )
-- диапазон значений
local amount = string.gsub( value.amount, '^%+', '' )
local lang = mw.language.getContentLanguage()
local langCode = lang:getCode()
local function formatNum( number, sigfig )
local multiplier = ''
if options.countByThousands then
local powers = options.i18n.thousandPowers
local pos = 1
while math.abs( number ) >= 1000 and pos < #powers do
number = number / 1000
pos = pos + 1
end
multiplier = powers[ pos ]
if math.abs( number ) >= 100 then
sigfig = sigfig or 0
elseif math.abs( number ) >= 10 then
sigfig = sigfig or 1
else
sigfig = sigfig or 2
end
else
sigfig = sigfig or 12 -- округление до 12 знаков после запятой, на 13-м возникает ошибка в точности
end
local iMultiplier = 10^sigfig
number = math.floor( number * iMultiplier + 0.5 ) / iMultiplier
return string.gsub( lang:formatNum( number ), '^-', '−' ) .. multiplier
end
local out = formatNum( tonumber( amount ) )
if value.upperBound then
local diff = tonumber( value.upperBound ) - tonumber( amount )
if diff > 0 then -- временная провека, пока у большинства значений не будет убрано ±0
-- Пробуем понять до какого знака округлять
local integer, dot, decimals, _ = value.upperBound:match( '^+?-?(%d*)(%.?)(%d*)(.*)' )
local precision
if dot == '' then
precision = -integer:match( '0*$' ):len()
else
precision = #decimals
end
local bound = formatNum( diff, precision )
if string.match( bound, 'E%-(%d+)' ) then -- если в экспоненциальном формате
local digits = tonumber( string.match( bound, 'E%-(%d+)' ) ) - 2
bound = formatNum( diff * 10 ^ digits, precision )
bound = string.sub( bound, 0, 2 ) .. string.rep( '0', digits ) .. string.sub( bound, -string.len( bound ) + 2 )
end
out = out .. ' ± ' .. bound
end
end
if options.unit and options.unit ~= '' then
if options.unit ~= '-' then
out = out .. ' ' .. options.unit
end
elseif value.unit and string.match( value.unit, 'http://www.wikidata.org/entity/' ) then
local unitEntityId = string.gsub( value.unit, 'http://www.wikidata.org/entity/', '' )
if unitEntityId ~= 'undefined' then
local wbStatus, unitEntity = pcall( mw.wikibase.getEntity, unitEntityId )
if wbStatus == true and unitEntity then
if unitEntity.claims.P2370 and
unitEntity.claims.P2370[ 1 ].mainsnak.snaktype == 'value' and
not value.upperBound and
options.siConversion == true
then
local conversionToSiUnit = string.gsub( unitEntity.claims.P2370[ 1 ].mainsnak.datavalue.value.amount, '^%+', '' )
if math.floor( math.log10( conversionToSiUnit ) ) ~= math.log10( conversionToSiUnit ) then
-- Если не степени десятки (переводить сантиметры в метры не надо!)
local outValue = tonumber( amount ) * conversionToSiUnit
if outValue > 0 then
-- Пробуем понять до какого знака округлять
local integer, dot, decimals, _ = amount:match( '^(%d*)(%.?)(%d*)(.*)' )
local precision
if dot == '' then
precision = -integer:match( '0*$' ):len()
else
precision = #decimals
end
local adjust = math.log10( math.abs( conversionToSiUnit ) ) + math.log10( 2 )
local minPrecision = 1 - math.floor( math.log10( outValue ) + 2e-14 )
out = formatNum( outValue, math.max( math.floor( precision + adjust ), minPrecision ) )
else
out = formatNum( outValue, 0 )
end
unitEntityId = string.gsub( unitEntity.claims.P2370[ 1 ].mainsnak.datavalue.value.unit, 'http://www.wikidata.org/entity/', '' )
wbStatus, unitEntity = pcall( mw.wikibase.getEntity, unitEntityId )
end
end
local label = getLabelWithLang( context, options, unitEntity.id, nil, { "P5061", "P558", "P558" }, {
'P5061[language:' .. langCode .. ']',
'P558[P282:' .. writingSystemElementId .. ', P407:' .. langElementId .. ']',
'P558[!P282][!P407]'
} )
out = out .. ' ' .. label
end
end
end
return out
end
---Функция для оформления URL
---@param context table
---@param options table
---@param value string
local function formatUrlValue( context, options, value )
if not options.length or options.length == '' then
options.length = 25
end
local moduleUrl = require( 'Module:URL' )
return moduleUrl.formatUrlSingle( context, options, value )
end
local DATATYPE_CACHE = {}
---Get property datatype by ID.
---@param propertyId string Property ID, e.g. 'P123'.
---@return string Property datatype, e.g. 'commonsMedia', 'time' or 'url'.
local function getPropertyDatatype( propertyId )
if not propertyId or not string.match( propertyId, '^P%d+$' ) then
return nil
end
local cached = DATATYPE_CACHE[ propertyId ]
if cached ~= nil then
return cached
end
local wbStatus, propertyEntity = pcall( mw.wikibase.getEntity, propertyId )
if wbStatus ~= true or not propertyEntity then
return nil
end
mw.log("Loaded datatype " .. propertyEntity.datatype .. " of " .. propertyId .. ' from wikidata, consider passing datatype argument to formatProperty call or to Wikidata/config' )
DATATYPE_CACHE[ propertyId ] = propertyEntity.datatype
return propertyEntity.datatype
end
---@param datavalue table
---@return function
local function getPlainValueFunction( datavalue, _ )
if datavalue.type == 'wikibase-entityid' then
return function( _, _, value )
return getEntityIdFromValue( value )
end
elseif datavalue.type == 'string' then
return function( _, _, value )
return value
end
elseif datavalue.type == 'monolingualtext' then
return function( _, _, value )
return value.text
end
elseif datavalue.type == 'globecoordinate' then
return function( _, _, value )
return value.latitude .. ',' .. value.longitude
end
elseif datavalue.type == 'quantity' then
return function( _, _, value )
return value.amount
end
elseif datavalue.type == 'time' then
return function( _, _, value )
return value.time
end
end
throwError( 'unknown-datavalue-type' )
end
---@param datavalue table
---@param datatype string
---@return function
local function getDefaultValueFunction( datavalue, datatype )
-- вызов обработчиков по умолчанию для известных типов значений
if datavalue.type == 'wikibase-entityid' then
-- Entity ID
return function( context, options, value )
return formatEntityId( context, options, getEntityIdFromValue( value ) )
end
elseif datavalue.type == 'string' then
-- String
if datatype and datatype == 'commonsMedia' then
-- Media
return function( _, options, value )
return formatCommonsMedia( value, options )
end
elseif datatype and datatype == 'external-id' then
-- External ID
return function( _, options, value )
return formatExternalId( value, options )
end
elseif datatype and datatype == 'math' then
-- Math formula
return function( _, options, value )
return formatMath( value, options )
end
elseif datatype and datatype == 'url' then
-- URL
return formatUrlValue
end
return function( _, _, value )
return value
end
elseif datavalue.type == 'monolingualtext' then
-- моноязычный текст (строка с указанием языка)
return function( _, options, value )
if options.monolingualLangTemplate == 'lang' then
if value.language == CONTENT_LANGUAGE_CODE then
return value.text
end
return options.frame:expandTemplate{ title = 'lang-' .. value.language, args = { value.text } }
elseif options.monolingualLangTemplate == 'ref' then
return '<span class="lang" lang="' .. value.language .. '">' .. value.text .. '</span>' .. options.frame:expandTemplate{ title = 'ref-' .. value.language }
else
return '<span class="lang" lang="' .. value.language .. '">' .. value.text .. '</span>'
end
end
elseif datavalue.type == 'globecoordinate' then
-- географические координаты
return function( _, options, value )
return formatGlobeCoordinate( value, options )
end
elseif datavalue.type == 'quantity' then
return function( _, options, value )
return formatQuantity( value, options )
end
elseif datavalue.type == 'time' then
return function( context, options, value )
local moduleDate = require( 'Module:Wikidata/date' )
return moduleDate.formatDate( context, options, value )
end
end
-- во всех стальных случаях возвращаем ошибку
throwError( 'unknown-datavalue-type' )
end
---Функция для оформления значений (value)
---Подробнее о значениях см. d:Wikidata:Glossary/ru
---@param context table
---@param options table
---@param datavalue table
---@param datatype string
---@return string Оформленный текст
function formatDatavalue( context, options, datavalue, datatype )
if not context then error( 'context not specified' ); end
if not options then error( 'options not specified' ); end
if not datavalue then error( 'datavalue not specified' ); end
if not datavalue.value then error( 'datavalue.value is missing' ); end
-- проверка на указание специализированных обработчиков в параметрах,
-- переданных при вызове
if options.plain then
context.formatValueDefault = getPlainValueFunction( datavalue, datatype )
else
context.formatValueDefault = getDefaultValueFunction( datavalue, datatype )
end
local functionToCall = getUserFunction( options, 'value', context.formatValueDefault )
return functionToCall( context, options, datavalue.value )
end
local DEFAULT_BOUNDARIES = { os.time() * 1000, os.time() * 1000}
---Функция для оформления идентификатора сущности
---@param context table
---@param options table
---@param entityId string
---@return string Оформленный текст
function formatEntityId( context, options, entityId )
-- получение локализованного названия
local boundaries
if options.qualifiers then
boundaries = p.getTimeBoundariesFromQualifiers( context.frame, context, { qualifiers = options.qualifiers } )
end
if not boundaries then
boundaries = DEFAULT_BOUNDARIES
end
local label, labelLanguageCode = getLabelWithLang( context, options, entityId, boundaries )
-- определение соответствующей показываемому элементу категории
local category = context.extractCategory( options, { id = entityId } )
-- получение ссылки по идентификатору
local link = mw.wikibase.sitelink( entityId )
if link then
-- ссылка на категорию, а не добавление страницы в неё
if mw.ustring.match( link, '^' .. mw.site.namespaces[ 14 ].name .. ':' ) then
link = ':' .. link
end
if label and not options.rawArticle then
if labelLanguageCode ~= CONTENT_LANGUAGE_CODE then
label = '<span lang="' .. label .. '">' .. label .. '</span>'
end
local a = '[[' .. link .. '|' .. label .. ']]'
if CONTENT_LANGUAGE_CODE ~= labelLanguageCode and 'mul' ~= labelLanguageCode then
a = a .. getCategoryByCode( 'links-to-entities-with-missing-local-language-label' )
end
return a .. category
else
return '[[' .. link .. ']]' .. category
end
end
if label then -- TODO: возможно, лучше просто mw.wikibase.getLabel(entityId)
-- красная ссылка
-- TODO: разобраться, почему не всегда есть options.frame
local moduleRedLink = require( 'Module:Wikidata/redLink' )
local title = mw.title.new( label )
if title and not title.exists and options.frame then
local rawLabel = mw.wikibase.getLabel(entityId) or label -- без |text= и boundaries; or label - костыль
local redLink = moduleRedLink.formatRedLinkWithInfobox(rawLabel, label, entityId)
if CONTENT_LANGUAGE_CODE ~= labelLanguageCode and 'mul' ~= labelLanguageCode then
redLink = '<span lang="' .. labelLanguageCode .. '">' .. redLink .. '</span>' ..
getCategoryByCode( 'links-to-entities-with-missing-local-language-label' )
end
return redLink .. category
end
-- TODO: перенести до проверки на существование статьи
local addWdLink = false
if ( not options.format or options.format ~= 'text' )
and entityId ~= 'Q6581072' and entityId ~= 'Q6581097' -- TODO: переписать на format=text
then
addWdLink = true
end
-- одноимённая статья уже существует - выводится текст и ссылка на ВД
return moduleRedLink.formatText(label, entityId, addWdLink) .. category
end
-- сообщение об отсутвии локализованного названия
-- not good, but better than nothing
return '[[:d:' .. entityId .. '|' .. entityId .. ']]<span style="border-bottom: 1px dotted; cursor: help; white-space: nowrap" title="В Викиданных нет русской подписи к элементу. Вы можете помочь, указав русский вариант подписи.">?</span>' .. getCategoryByCode( 'links-to-entities-with-missing-label' ) .. category
end
---Функция для оформления утверждений (statement)
---Подробнее о утверждениях см. d:Wikidata:Glossary/ru
---@deprecated Use p.formatProperty() instead
---@param frame table
---@return string Строка оформленного текста, предназначенная для отображения в статье
function p.formatStatements( frame )
return p.formatProperty( frame )
end
---Получение параметров, которые обычно используются для вывода свойства.
---@param propertyId string
---@param datatype string
---@param params table
function getPropertyParams( propertyId, datatype, params )
local config = getConfig()
-- Различные уровни настройки параметров, по убыванию приоритета
local propertyParams = {}
-- 1. Параметры, указанные явно при вызове
if params then
for key, value in pairs( params ) do
if value ~= '' then
propertyParams[ key ] = value
end
end
end
if toBoolean( propertyParams.plain, false ) then
propertyParams.separator = propertyParams.separator or ', '
propertyParams.conjunction = propertyParams.conjunction or ', '
else
-- 2. Настройки конкретного параметра
if config.properties and config.properties[ propertyId ] then
for key, value in pairs( config.properties[ propertyId ] ) do
if propertyParams[ key ] == nil then
propertyParams[ key ] = value
end
end
end
-- 3. Указанный пресет настроек
if propertyParams.preset and config.presets and
config.presets[ propertyParams.preset ]
then
for key, value in pairs( config.presets[ propertyParams.preset ] ) do
if propertyParams[ key ] == nil then
propertyParams[ key ] = value
end
end
end
datatype = datatype or params.datatype or propertyParams.datatype or getPropertyDatatype( propertyId )
if propertyParams.datatype == nil then
propertyParams.datatype = datatype
end
-- 4. Настройки для типа данных
if datatype and config.datatypes and config.datatypes[ datatype ] then
for key, value in pairs( config.datatypes[ datatype ] ) do
if propertyParams[ key ] == nil then
propertyParams[ key ] = value
end
end
end
-- 5. Общие настройки для всех свойств
if config.global then
for key, value in pairs( config.global ) do
if propertyParams[ key ] == nil then
propertyParams[ key ] = value
end
end
end
end
return propertyParams
end
---Функция для оформления утверждений (statement)
---Подробнее о утверждениях см. d:Wikidata:Glossary/ru
---@param frame table
---@return string Строка оформленного текста, предназначенная для отображения в статье
function p.formatProperty( frame )
local args = copyTo( frame.args, {} )
-- проверка на отсутствие обязательного параметра property
if not args.property then
throwError( 'property-param-not-provided' )
end
local override
local propertyId = mw.language.getContentLanguage():ucfirst( string.gsub( args.property, '([^Pp0-9].*)$', function(w)
if string.sub( w, 1, 1 ) == '~' then
override = w
end
return ''
end ) )
if override then
args[ override:match( '[,~]([^=]*)=' ) ] = override:match( '=(.*)' )
args.property = propertyId
end
-- проброс всех параметров из шаблона {wikidata} и параметра from откуда угодно
local p_frame = frame
while p_frame do
if p_frame:getTitle() == mw.site.namespaces[ 10 ].name .. ':Wikidata' then
copyTo( p_frame.args, args, true )
end
if p_frame.args and p_frame.args.from and p_frame.args.from ~= '' then
args.entityId = p_frame.args.from
else
args.entityId = mw.wikibase.getEntityIdForCurrentPage()
end
p_frame = p_frame:getParent()
end
args = getPropertyParams( propertyId, nil, args )
local datatype = args.datatype
-- перевод итоговых значений флагов в true/false и добавление значений
-- по умолчанию только в том случае, если они нигде не были указаны ранее
args.plain = toBoolean( args.plain, false )
args.nocat = not args.plain and toBoolean( args.nocat, false )
args.references = not args.plain and toBoolean( args.references, true )
-- если значение передано в параметрах вызова то выводим только его
if args.value and args.value ~= '' then
-- специальное значение для скрытия Викиданных
if args.value == '-' then
return ''
end
local value = args.value
-- опция, запрещающая оформление значения, поэтому никак не трогаем
if args.plain then
return value
end
local context = initContext( args )
-- обработчики по типу значения
local wrapperExtraArgs = {}
if args[ 'value-module' ] and args[ 'value-function' ] and not string.find( value, '[%[%]%{%}]' ) then
local func = getUserFunction( args, 'value' )
value = func( context, args, value )
elseif datatype == 'commonsMedia' then
value = formatCommonsMedia( value, args )
elseif datatype == 'external-id' and not string.find( value, '[%[%]%{%}]' ) then
wrapperExtraArgs[ 'data-wikidata-external-id' ] = mw.text.killMarkers( value )
value = formatExternalId( value, args )
--elseif datatype == 'math' then
-- args.frame = frame -- костыль: в formatMath нужно frame:extensionTag
-- value = formatMath( value, args )
elseif datatype == 'url' then
value = formatUrlValue( context, args, value )
end
-- оборачиваем в тег для JS-функций
if string.match( propertyId, '^P%d+$' ) then
value = mw.text.trim( value )
-- временная штрафная категория для исправления табличных вставок
local allowTables = getPropertyParams( propertyId, nil, {} ).allowTables
if not allowTables
and string.match( value, '<t[dhr][ >]' )
-- and not string.match( value, '<table[ >]' )
-- and not string.match( value, '^%{%|' )
then
value = value .. getCategoryByCode( 'value-contains-table', propertyId )
else
value = wrapStatement( value, propertyId, nil, wrapperExtraArgs )
end
end
return value
end
-- ability to disable loading Wikidata
if args.entityId == '-' then
return ''
end
g_frame = frame
-- после проверки всех аргументов -- вызов функции оформления для свойства (набора утверждений)
return formatProperty( args )
end
---Функция проверки на присутствие источника в списке нерекомендованных.
---@param snaks table
---@return boolean
local function isReferenceDeprecated( snaks )
if not snaks then
return false
end
if snaks.P248
and snaks.P248[ 1 ]
and snaks.P248[ 1 ].datavalue
and snaks.P248[ 1 ].datavalue.value.id
then
local entityId = snaks.P248[ 1 ].datavalue.value.id
if getConfig( 'deprecatedSources', entityId ) then
return true
end
elseif snaks.P1433
and snaks.P1433[ 1 ]
and snaks.P1433[ 1 ].datavalue
and snaks.P1433[ 1 ].datavalue.value.id
then
local entityId = snaks.P1433[ 1 ].datavalue.value.id
if getConfig( 'deprecatedSources', entityId ) then
return true
end
end
return false
end
---Функция оформления ссылок на источники (reference)
---Подробнее о ссылках на источники см. d:Wikidata:Glossary/ru
---
---Экспортируется в качестве зарезервированной точки для вызова из функций-расширения вида claim-module/claim-function через context
---Вызов из других модулей напрямую осуществляться не должен (используйте frame:expandTemplate вместе с одним из специлизированных шаблонов вывода значения свойства).
---@param context table
---@param options table
---@param statement table
---@return string Оформленные примечания для отображения в статье
function formatRefs( context, options, statement )
if not context then error( 'context not specified' ); end
if not options then error( 'options not specified' ); end
if not options.entityId then error( 'options.entityId missing' ); end
if not statement then error( 'statement not specified' ); end
if not outputReferences then
return ''
end
---@type string[]
local references = {}
if statement.references then
local hasNotDeprecated = false
local displayCount = 0
for _, reference in pairs( statement.references ) do
if not isReferenceDeprecated( reference.snaks ) then
hasNotDeprecated = true
end
end
for _, reference in pairs( statement.references ) do
local display = true
if hasNotDeprecated then
if isReferenceDeprecated( reference.snaks ) then
display = false
end
end
if displayCount >= 2 then
if options.entityId and options.property then
local propertyId = mw.ustring.match( options.property, '^[Pp][0-9]+' ) -- TODO: обрабатывать не тут, а раньше
local moreReferences = '<sup>[[d:' .. options.entityId .. '#' .. string.upper( propertyId ) .. '|[…]]]</sup>'
table.insert( references, moreReferences )
end
break
end
if display == true then
---@type string
local refText = moduleSources.renderReference( g_frame, options.entityId, reference )
if refText and refText ~= '' then
table.insert( references, refText )
displayCount = displayCount + 1
end
end
end
end
return table.concat( references )
end
return p
4558f762f30c6ebfb9f5333dbd7ebda83c6873f2
Модуль:Sources
828
32
62
61
2025-01-25T21:00:17Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
---@alias args table
---@alias frame { args: args, extensionTag: function, newChild: ( fun( args: args ): frame ) }
---@alias source { publication: source, [string]: any }
---@alias value: string | { id: string }
---@alias snak { datatype: string, snaktype: string, datavalue: { type: string, value: value } }
---@alias snaks table<string, table<number, snak>>
---@alias statement { mainsnak: snak, rank: string, qualifiers: snaks }
---@alias statements table<string, table<number, statement>>
---@alias map { name: string, ids: string[] }[]>
---@type table
local p = {}
---@type table<string, string>
local NORMATIVE_DOCUMENTS = {
Q20754888 = 'Закон Российской Федерации',
Q20754884 = 'Закон РСФСР',
Q20873831 = 'Распоряжение Президента Российской Федерации',
Q20873834 = 'Указ исполняющего обязанности Президента Российской Федерации',
Q2061228 = 'Указ Президента Российской Федерации',
}
---@type table<string, string>
local LANG_CACHE = {
Q150 = 'fr',
Q188 = 'de',
Q1321 = 'es',
Q1860 = 'en',
Q652 = 'it',
Q7737 = 'ru',
Q8798 = 'uk',
}
---@type map
local PROPERTY_MAP = {
{ name = 'sourceId', ids = { 'P248', 'P805' } },
{ name = 'lang', ids = { 'P407', 'P364' } },
{ name = 'author', ids = { 'P50', 'P2093' } },
{ name = 'part', ids = { 'P958', 'P1810' } },
{ name = 'title', ids = { 'P1476' } },
{ name = 'subtitle', ids = { 'P1680' } },
{ name = 'url', ids = { 'P953', 'P1065', 'P854', 'P973', 'P2699', 'P888' } },
{ name = 'editor', ids = { 'P98' } },
{ name = 'translator', ids = { 'P655' } },
{ name = 'publication-id', ids = { 'P1433' } },
{ name = 'edition', ids = { 'P393' } },
{ name = 'publisher', ids = { 'P123' } },
{ name = 'place', ids = { 'P291' } },
{ name = 'volume', ids = { 'P478' } },
{ name = 'issue', ids = { 'P433' } },
{ name = 'dateOfCreation', ids = { 'P571' } },
{ name = 'dateOfPublication', ids = { 'P577' } },
{ name = 'pages', ids = { 'P304' } },
{ name = 'numberOfPages', ids = { 'P1104' } },
{ name = 'tirage', ids = { 'P1092' } },
{ name = 'isbn', ids = { 'P212', 'P957' } },
{ name = 'issn', ids = { 'P236' } },
-- { name = 'accessdate', ids = { 'P813' } }, -- disable, creates duplicate references
{ name = 'docNumber', ids = { 'P1545' } },
{ name = 'type', ids = { 'P31' } },
{ name = 'arxiv', ids = { 'P818' } },
{ name = 'doi', ids = { 'P356' } },
{ name = 'pmid', ids = { 'P698' } },
}
-- table.insert( PROPERTY_MAP.url, 'P856' ) -- only as qualifier
---@type map
local PUBLICATION_PROPERTY_MAP = mw.clone( PROPERTY_MAP )
---@type string[]
local monthGen = { 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря' }
---@type string
local i18nDefaultLanguage = mw.language.getContentLanguage():getCode()
p.i18nDefaultLanguage = i18nDefaultLanguage
---@type string
local i18nEtAlDefault = ' et al.'
---@type table<string, string>
local i18nEtAl = {
ru = ' и др.',
uk = ' та ін.',
}
---@type table<string, string>
local i18nEditors = {
fr = '',
de = 'Hrsg.: ',
es = '',
en = '',
it = '',
ru = 'под ред. ',
uk = 'за ред. ',
}
---@type table<string, string>
local i18nTranslators = {
fr = '',
de = '',
es = '',
en = '',
it = '',
ru = 'пер. ',
uk = 'пер. ',
}
---@type table<string, string>
local i18nVolume = {
de = 'Vol.',
fr = 'Vol.',
es = 'Vol.',
en = 'Vol.',
it = 'Vol.',
ru = 'Т.',
uk = 'Т.',
}
---@type table<string, string>
local i18nIssue = {
en = 'Iss.',
ru = 'вып.',
uk = 'вип.',
}
---@type table<string, string>
local i18nPages = {
fr = 'P.',
de = 'S.',
es = 'P.',
en = 'P.',
it = 'P.',
ru = 'С.',
uk = 'С.',
}
---@type table<string, string>
local i18nNumberOfPages = {
en = 'p.',
ru = 'с.',
}
---@type table<string, string>
local i18nTirage = {
en = 'ed. size: %d',
ru = '%d экз.',
}
---@param args args
---@return source
local function getFilledArgs( args )
---@type source
local data = {}
for key, value in pairs( args ) do
if mw.text.trim( value ) ~= '' then
if key == 1 then
key = 'sourceId'
end
data[ key ] = mw.text.trim( value )
end
end
return data
end
---Returns formatted pair {Family name(s), First name(s)}
---@param fullName string
---@return table<number, string>
local function tokenizeName( fullName )
local space = '%s+' -- matches single or more spacing character
local name = "(%a[%a%-']*)%.?" -- matches single name, have to start with letter, can contain apostrophe and hyphen, may end with dot
local surname = "(%a[%a%-']*)" -- same as name, but can't end with dot
local surnamePrefixes = { 'ван', 'van', 'де', 'de' }
local nm, nm2, srn, srn2, pref
fullName = ' ' .. fullName .. ' '
fullName = mw.ustring.gsub( fullName, ' оглы ', ' ' )
fullName = mw.text.trim( fullName )
-- Surname, Name
local pattern = '^' .. surname .. ',' .. space .. name .. '$'
srn, nm = mw.ustring.match( fullName, pattern )
if srn then
return {
srn,
mw.ustring.sub( nm, 1, 1 ) .. '.'
}
end
-- Surname, Name prefix
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. surname .. ',' .. space .. name .. space .. '(' .. surnamePrefix .. ')' .. '$'
srn, nm, pref = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '.' }
end
end
-- Surname, Name Name
pattern = '^' .. surname .. ',' .. space .. name .. space .. name .. '$'
srn, nm, nm2 = mw.ustring.match( fullName, pattern )
if srn then
return {
srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
-- Surname Surname, Name
pattern = '^' .. surname .. space .. surname .. ',' .. space .. name .. '$'
srn, srn2, nm = mw.ustring.match( fullName, pattern )
if srn then
return {
srn .. ' ' .. srn2,
mw.ustring.sub( nm, 1, 1 ) .. '.'
}
end
-- Name Name Surname
pattern = '^' .. name .. space .. name .. space .. surname .. '$'
nm, nm2, srn = mw.ustring.match( fullName, pattern )
if srn then
return {
srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
-- Name Name prefix Surname
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. name .. space .. name .. space .. '(' .. surnamePrefix .. ')' .. space .. surname .. '$'
nm, nm2, pref, srn = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
end
-- Surname, Name Name prefix
for _, surnamePrefix in pairs( surnamePrefixes ) do
pattern = '^' .. surname .. ',' .. space .. name .. space .. name .. space .. '(' .. surnamePrefix .. ')' .. '$'
srn, nm, nm2, pref = mw.ustring.match( fullName, pattern )
if srn then
return {
mw.ustring.sub( pref ) .. ' ' .. srn,
mw.ustring.sub( nm, 1, 1 ) .. '. ' .. mw.ustring.sub( nm2, 1, 1 ) .. '.'
}
end
end
-- Name{1,4} Surname
for k = 1, 4 do
pattern = '^' .. string.rep( name .. space, k ) .. surname .. '$'
---@type string[]
local matched = { mw.ustring.match( fullName, pattern ) }
if #matched ~= 0 then
for j = 1, k do
matched[ j ] = mw.ustring.sub( matched[ j ], 1, 1 )
end
return {
matched[ k + 1 ],
table.concat( matched, '. ', 1, k ) .. '.'
}
end
end
-- Surname Name{1,4}
for k = 1, 4 do
pattern = '^' .. surname .. string.rep( space .. name, k ) .. '$'
---@type string[]
local matched = { mw.ustring.match( fullName, pattern ) }
if #matched ~= 0 then
for j = 2, k + 1 do
matched[ j ] = mw.ustring.sub( matched[ j ], 1, 1 )
end
return {
matched[ 1 ],
table.concat( matched, '. ', 2, k + 1 ) .. '.'
}
end
end
return { fullName }
end
---@param fullName string | nil
---@return string | nil
local function personNameToAuthorName( fullName )
if not fullName then
return nil
end
local tokenized = tokenizeName( fullName )
if #tokenized == 1 then
return tokenized[ 1 ]
end
return tokenized[ 1 ] .. ' ' .. tokenized[ 2 ]
end
---@param fullName string | nil
---@return string | nil
local function personNameToResponsibleName( fullName )
if not fullName then
return nil
end
local tokenized = tokenizeName( fullName )
if #tokenized == 1 then
return tokenized[ 1 ]
end
return tokenized[ 2 ] .. ' ' .. tokenized[ 1 ]
end
---@alias options { separator: string, conjunction: string, format: ( fun( data: string ): string ), nolinks: boolean, preferids: boolean, short: boolean }
---@type options
local options_commas = {
separator = ', ',
conjunction = ', ',
format = function( data ) return data end,
nolinks = false,
preferids = false,
short = false,
}
---@type options
local options_commas_short = mw.clone( options_commas )
options_commas_short.short = true
---@type options
local options_commas_it_short = mw.clone( options_commas_short )
options_commas_it_short.format = function( data ) return "''" .. data .. "''" end
---@type options
local options_commas_nolinks = mw.clone( options_commas )
options_commas_nolinks.nolinks = true
---@type options
local options_citetypes = {
separator = ' ',
conjunction = ' ',
format = function( data ) return 'citetype_' .. data end,
nolinks = true ,
preferids = true,
short = false,
}
---@type options
local options_commas_authors = mw.clone( options_commas )
options_commas_authors.format = personNameToAuthorName
---@type options
local options_commas_responsible = mw.clone( options_commas )
options_commas_responsible.format = personNameToResponsibleName
---@type options
local options_ids = {
separator = '; ',
conjunction = '; ',
format = function( id ) return id end,
nolinks = true,
preferids = false,
short = false,
}
---@type options
local options_arxiv = mw.clone( options_ids )
options_arxiv.format = function( id ) return '[https://arxiv.org/abs/' .. id .. ' arXiv:' .. id .. ']' end
---@type options
local options_doi = mw.clone( options_ids )
options_doi.format = function( doi ) return '[https://dx.doi.org/' .. doi .. ' doi:' .. doi .. ']' end
---@type options
local options_issn = mw.clone( options_ids )
options_issn.format = function( issn ) return '[https://www.worldcat.org/issn/' .. issn .. ' ' .. issn .. ']' end
---@type options
local options_pmid = mw.clone( options_ids )
options_pmid.format = function( pmid ) return '[https://www.ncbi.nlm.nih.gov/pubmed/?term=' .. pmid .. ' PMID:' .. pmid .. ']' end
---@param str string | nil
---@return boolean
local function isEmpty( str )
return not str or #str == 0
end
---@param allQualifiers snaks
---@param qualifierPropertyId string
---@return string | nil
local function getSingleStringQualifierValue( allQualifiers, qualifierPropertyId )
if not allQualifiers or not allQualifiers[ qualifierPropertyId ] then
return nil
end
---@type table<number, snak>
local propertyQualifiers = allQualifiers[ qualifierPropertyId ]
for _, qualifier in pairs( propertyQualifiers ) do
if ( qualifier
and qualifier.datatype == 'string'
and qualifier.datavalue
and qualifier.datavalue.type == 'string'
and qualifier.datavalue.value ~= ''
) then
return qualifier.datavalue.value
end
end
return nil
end
---@param data table
---@param resultProperty string
---@return void
local function appendImpl_toTable( data, resultProperty )
if not data[ resultProperty ] then
data[ resultProperty ] = {}
elseif ( type( data[ resultProperty ] ) == 'string' or ( type( data[ resultProperty ] ) == 'table' and type( data[ resultProperty ].id ) == 'string' ) ) then
data[ resultProperty ] = { data[ resultProperty ] }
end
end
---@param datavalue table
---@param qualifiers snaks
---@param data table
---@param propertyName string
---@param options table
local function appendImpl( datavalue, qualifiers, data, propertyName, options )
data[ propertyName ] = data[ propertyName ] or {}
if propertyName == 'issn' then
table.insert( data[ propertyName ], datavalue.value )
elseif propertyName == 'url' or datavalue.type == 'url' then
local value = datavalue.value
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], value )
elseif datavalue.type == 'string' then
local value = getSingleStringQualifierValue( qualifiers, 'P1932' )
if not value then
value = getSingleStringQualifierValue( qualifiers, 'P1810' )
end
if not value then
value = datavalue.value
if options.format then
value = options.format( value )
end
end
appendImpl_toTable(data, propertyName)
local pos = getSingleStringQualifierValue( qualifiers, 'P1545' )
if pos then
table.insert( data[ propertyName ], tonumber(pos), value )
else
table.insert( data[ propertyName ], value )
end
elseif datavalue.type == 'monolingualtext' then
local value = datavalue.value.text
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], value )
elseif datavalue.type == 'quantity' then
local value = datavalue.value.amount
if ( mw.ustring.sub( value , 1, 1 ) == '+' ) then
value = mw.ustring.sub( value , 2 )
end
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], value )
elseif datavalue.type == 'wikibase-entityid' then
local pos = getSingleStringQualifierValue( qualifiers, 'P1545' )
local value = datavalue.value
appendImpl_toTable(data, propertyName)
local label = getSingleStringQualifierValue( qualifiers, 'P1932' )
if not label then
label = getSingleStringQualifierValue( qualifiers, 'P1810' )
end
local toInsert = {
id = value.id,
label = label
}
if pos and tonumber( pos ) then
table.insert( data[ propertyName ], tonumber( pos ), toInsert )
else
table.insert( data[ propertyName ], toInsert )
end
elseif datavalue.type == 'time' then
local value = datavalue.value
if options.format then
value = options.format( value )
end
appendImpl_toTable( data, propertyName )
table.insert( data[ propertyName ], tostring( value.time ) )
end
end
---@param entityId string
---@param propertyId string
---@return table<number, statement>
local function getAllStatements( entityId, propertyId )
---@type boolean, table<number, statement>
local wdStatus, statements = pcall( mw.wikibase.getAllStatements, entityId, propertyId )
if wdStatus and statements then
return statements
end
return {}
end
---@param entityId string
---@param propertyId string
---@return table<number, statement>
local function getBestStatements( entityId, propertyId )
---@type boolean, table<number, statement>
local wdStatus, statements = pcall( mw.wikibase.getBestStatements, entityId, propertyId )
if wdStatus and statements then
return statements
end
return {}
end
---@param entityId string
---@param projectToCheck string?
---@return string | nil
local function getSitelink( entityId, projectToCheck )
---@type boolean, string
local wbStatus, sitelink
if projectToCheck then
wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId, projectToCheck )
else
wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId )
end
if not wbStatus then
return nil
end
return sitelink
end
---@param args any[]
---@return any | nil
local function coalesce( args )
for _, arg in pairs( args ) do
if not isEmpty( arg ) then return arg end
end
return nil
end
---@param value any
---@return string | nil
local function getSingle( value )
if type( value ) == 'string' then
return tostring( value )
elseif type( value ) == 'table' then
if value.id then
return tostring( value.id )
end
for _, tableValue in pairs( value ) do
return getSingle( tableValue )
end
end
return nil
end
---@param langEntityId string
---@return string | nil
local function getLangCode( langEntityId )
if not langEntityId then
return nil
end
langEntityId = getSingle( langEntityId )
if not string.match( langEntityId, '^Q%d+$' ) then
return langEntityId
end
local cached = LANG_CACHE[ langEntityId ]
if cached then
if cached == '' then
return nil
end
return cached
end
local claims = getBestStatements( langEntityId, 'P424' )
for _, claim in pairs( claims ) do
if claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
then
LANG_CACHE[ langEntityId ] = claim.mainsnak.datavalue.value
return claim.mainsnak.datavalue.value
end
end
LANG_CACHE[ langEntityId ] = ''
return nil
end
---@param entityId string
---@param propertyId string
---@param data source
---@param propertyName string
---@param options table?
---@return void
local function appendEntitySnaks( entityId, propertyId, data, propertyName, options )
options = options or {}
-- do not populate twice
if data[ propertyName ] and ( propertyName ~= 'author' or data[ propertyId ] ) then
return
end
local statements = getBestStatements( entityId, propertyId )
if propertyName == 'author' then
data[ propertyId ] = true
end
local lang = getLangCode( data.lang ) or i18nDefaultLanguage
if propertyId == 'P1680' then -- if there is a default language
for _, statement in pairs( statements ) do
if statement and
statement.mainsnak and
statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.language == lang
then
--found default language string
appendImpl( statement.mainsnak.datavalue, statement.qualifiers, data, propertyName, options )
return
end
end
end
for _, statement in pairs( statements ) do
if statement and statement.mainsnak and statement.mainsnak.datavalue then
appendImpl( statement.mainsnak.datavalue, statement.qualifiers or {}, data, propertyName, options )
if propertyName == 'publication-id' and statement.qualifiers then
data[ 'publication-qualifiers' ] = statement.qualifiers
end
end
end
end
---@param claims table<number, statement>
---@param qualifierPropertyId string
---@param result table
---@param resultPropertyId string
---@param options table
---@return void
local function appendQualifiers( claims, qualifierPropertyId, result, resultPropertyId, options )
-- do not populate twice
if not claims or result[ resultPropertyId ] then
return
end
for _, claim in pairs( claims ) do
if claim.qualifiers and claim.qualifiers[ qualifierPropertyId ] then
---@type table<number, snak>
local propertyQualifiers = claim.qualifiers[ qualifierPropertyId ]
for _, qualifier in pairs( propertyQualifiers ) do
if qualifier and qualifier.datavalue then
appendImpl( qualifier.datavalue, nil, result, resultPropertyId, options )
end
end
end
end
end
---@param entityId string
---@param propertyId string
---@param value any
---@return table<number, statement>
local function findClaimsByValue( entityId, propertyId, value )
local result = {}
local claims = getAllStatements( entityId, propertyId )
for _, claim in pairs( claims ) do
if ( claim.mainsnak and claim.mainsnak.datavalue ) then
local datavalue = claim.mainsnak.datavalue
if ( datavalue.type == "string" and datavalue.value == value ) or
( datavalue.type == "wikibase-entityid" and
datavalue.value[ "entity-type" ] == "item" and
tostring( datavalue.value.id ) == value )
then
table.insert( result, claim )
end
end
end
return result
end
---@param entityId string
---@param typeEntityId string
---@return boolean
local function isInstanceOf( entityId, typeEntityId )
return findClaimsByValue( entityId, 'P31', typeEntityId )[ 1 ] ~= nil
end
---@param entityId string
---@param typeEntityIds string[]
---@return string
---@todo Rewrite
local function getFirstType( entityId, typeEntityIds )
for _, typeEntityId in pairs( typeEntityIds ) do
if isInstanceOf( entityId, typeEntityId ) then
return typeEntityId
end
end
return nil
end
---@param snaks snaks
---@param data source
---@param map map
---@return void
local function populateDataFromSnaks( snaks, data, map )
for _, row in ipairs( map ) do
local parameterName, propertyIds = row.name, row.ids
for _, propertyId in pairs( propertyIds ) do
if not data[ parameterName ] and snaks[ propertyId ] then
local options = {}
if propertyId == 'P888' then
options = { format = function( id ) return 'http://www.jstor.org/stable/' .. id end }
end
for _, snak in pairs( snaks[ propertyId ] ) do
if snak and snak.datavalue then
appendImpl( snak.datavalue, {}, data, parameterName, options )
end
end
end
end
end
end
---@param entityId string | nil
---@param data source
---@param map map
---@return void
local function populateDataFromEntity( entityId, data, map )
if not data.title then
if not isEmpty( entityId ) then
local optionsAsLinks = { format = function( text ) return { id = entityId, label = text } end }
appendEntitySnaks( entityId, 'P1476', data, 'title', optionsAsLinks )
else
appendEntitySnaks( entityId, 'P1476', data, 'title', {} )
end
appendEntitySnaks( entityId, 'P1680', data, 'subtitle', {} )
end
local bookSeriesStatements = getBestStatements( entityId, 'P361' )
for _, statement in pairs( bookSeriesStatements ) do
if statement and
statement.mainsnak and
statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.id
then
local possibleBookSeriesEntityId = statement.mainsnak.datavalue.value.id
if isInstanceOf( possibleBookSeriesEntityId, 'Q277759' ) then
appendImpl_toTable( data, 'bookSeries' )
table.insert( data.bookSeries, { id = possibleBookSeriesEntityId } )
appendQualifiers( { statement }, 'P478', data, 'bookSeriesVolume', {} )
appendQualifiers( { statement }, 'P433', data, 'bookSeriesIssue', {} )
end
end
end
for _, row in ipairs( map ) do
local parameterName, propertyIds = row.name, row.ids
for _, propertyId in pairs( propertyIds ) do
local options = {}
if propertyId == 'P888' then
options = { format = function( id ) return 'http://www.jstor.org/stable/' .. id end }
end
appendEntitySnaks( entityId, propertyId, data, parameterName, options )
end
end
end
---@param data source
---@return void
local function expandPublication( data )
if not data[ 'publication-id' ] then
return
end
local publicationId = getSingle( data[ 'publication-id' ] )
data.publication = {}
for key, value in pairs( data ) do
if not string.match( key, '^publication-' ) then
data.publication[ key ] = value
end
end
data.publication.sourceId = publicationId
data.publication.title = data[ 'publication-title' ]
data.publication.subtitle = data[ 'publication-subtitle' ]
if data[ 'publication-qualifiers' ] then
populateDataFromSnaks( data[ 'publication-qualifiers' ], data.publication, PUBLICATION_PROPERTY_MAP )
end
populateDataFromEntity( publicationId, data.publication, PUBLICATION_PROPERTY_MAP )
if type( data.publication.title ) == 'table' and data.publication.title[ 1 ] then
data.publication.title = data.publication.title[ 1 ]
end
if type( data.publication.subtitle ) == 'table' and data.publication.subtitle[ 1 ] then
data.publication.subtitle = data.publication.subtitle[ 1 ]
end
for key, value in pairs( data.publication ) do
if key ~= 'sourceId' and key ~= 'title' and key ~= 'subtitle' and key ~= 'url' and not data[ key ] then
data[ key ] = value
end
end
end
---@param data source
---@return void
local function expandBookSeries( data )
local bookSeries = data.bookSeries
if not bookSeries then
return
end
-- use only first one
if type( bookSeries ) == 'table' and bookSeries[ 1 ] and bookSeries[ 1 ].id then
data.bookSeries = bookSeries[ 1 ]
bookSeries = data.bookSeries
end
if not bookSeries or not bookSeries.id then
return
end
appendEntitySnaks( bookSeries.id, 'P123', data, 'publisher', {} )
appendEntitySnaks( bookSeries.id, 'P291', data, 'place', {} )
appendEntitySnaks( bookSeries.id, 'P236', data, 'issn', {} )
end
---@param entityId string
---@return string | nil
local function getNormativeTitle( entityId )
local possibleTypeIds = {}
for typeId, _ in pairs( NORMATIVE_DOCUMENTS ) do
table.insert( possibleTypeIds, typeId )
end
local foundTypeId = getFirstType( entityId, possibleTypeIds )
if foundTypeId then
return NORMATIVE_DOCUMENTS[ foundTypeId ]
end
return nil
end
---@param urls table<number, string> | string
---@param text string
---@return string
local function wrapInUrl( urls, text )
local url = getSingle( urls )
if string.sub( url, 1, 1 ) == ':' then
return '[[' .. url .. '|' .. text .. ']]'
else
return '[' .. url .. ' ' .. text .. ']'
end
end
---@param entityId string
---@param lang string
---@return string
local function getElementLink( entityId, lang )
local sitelink = getSitelink( entityId, nil )
if sitelink then
return ':' .. sitelink
end
if lang ~= 'mul' then
-- link to entity in source language
sitelink = getSitelink( entityId, lang .. 'wiki' )
if sitelink then
return ':' .. lang .. ':' .. sitelink
end
end
return ':d:' .. entityId
end
---@param entityId string
---@param lang string
---@return string
local function getLabel( entityId, lang )
local wbStatus, label = pcall( mw.wikibase.getLabelByLang, entityId, lang )
if not wbStatus then
return ''
end
if label and label ~= '' then
return label
end
wbStatus, label = pcall( mw.wikibase.getLabel, entityId )
if not wbStatus then
return ''
end
return label or ''
end
---@param lang string
---@param entityId string
---@param customTitle string
---@param options table
local function renderLink( lang, entityId, customTitle, options )
if not entityId then
error( 'entityId is not specified' )
end
if type( entityId ) ~= 'string' then
error( 'entityId is not string, but ' .. type( entityId ) )
end
if type( customTitle or '' ) ~= 'string' then
error( 'customTitle is not string, but ' .. type( customTitle ) )
end
local title = customTitle
-- ISO 4
if isEmpty( title ) then
local propertyStatements = getBestStatements( entityId, 'P1160' )
for _, claim in pairs( propertyStatements ) do
if ( claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
and claim.mainsnak.datavalue.value.language == lang
) then
title = claim.mainsnak.datavalue.value.text
-- mw.log( 'Got title of ' .. entityId .. ' from ISO 4 claim: «' .. title .. '»' )
break
end
end
end
-- official name P1448
-- short name P1813
if isEmpty( title ) and options.short then
local propertyStatements = getBestStatements( entityId, 'P1813' )
for _, claim in pairs( propertyStatements ) do
if ( claim
and claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.value
and claim.mainsnak.datavalue.value.language == lang
) then
title = claim.mainsnak.datavalue.value.text
-- mw.log( 'Got title of ' .. entityId .. ' from short name claim: «' .. title .. '» (' .. lang .. ')' )
break
end
end
end
-- person name P1559
-- labels
if isEmpty( title ) then
title = getLabel( entityId, lang )
-- mw.log( 'Got title of ' .. entityId .. ' from label: «' .. title .. '» (' .. lang .. ')' )
end
local actualText = title or '\'\'(untranslated)\'\''
local link = getElementLink( entityId, lang )
return wrapInUrl( link, actualText )
end
---@param lang string
---@param value value
---@param options options
---@return string
local function asString( lang, value, options )
if type( value ) == 'string' then
return options.format( value )
end
if type( value ) ~= 'table' then
return options.format( '(unknown type)' )
end
if value.id then
-- this is link
if type( value.label or '' ) ~= 'string' then
mw.logObject( value, 'error value' )
error( 'label of table value is not string but ' .. type( value.label ) )
end
local title
if options.preferids then
title = value.id
elseif options.nolinks then
title = value.label or getLabel( value.id, lang )
else
title = renderLink( lang, value.id, value.label, options )
end
if title == '' then
title = "''(untranslated title)''"
end
return options.format( title )
end
local resultList = {}
for _, tableValue in pairs( value ) do
table.insert( resultList, asString( lang, tableValue, options ) )
end
return mw.text.listToText( resultList, options.separator, options.conjunction )
end
---@param entityId string
---@param data source
---@return source
local function populateSourceDataImpl( entityId, data, map )
local wsLink = getSitelink( entityId, 'ruwikisource' )
if wsLink and not mw.ustring.gmatch( wsLink, 'Категория:' ) then
data.url = ":ru:s:" .. wsLink
end
populateDataFromEntity( entityId, data, map )
local normativeTitle = getNormativeTitle( entityId )
if normativeTitle then
local y, m, d = mw.ustring.match( getSingle( data.dateOfCreation ) , "(%-?%d+)%-(%d+)%-(%d+)T" )
y, m, d = tonumber( y ),tonumber( m ), tonumber( d )
local title = asString( 'ru', data.title, options_commas_nolinks )
local docNumber = getSingle( data.docNumber )
data.title = {
normativeTitle ..
" от " .. tostring( d ) .. " " .. monthGen[ m ] .. " " .. tostring( y ) .. " г." ..
( docNumber and ( " № " .. docNumber ) or '' ) ..
' «' .. title.. '»'
}
end
if not data.title then
local lang = getLangCode( data.lang ) or i18nDefaultLanguage
local label = getLabel( entityId, lang )
if label ~= '' then
data.title = { label }
end
end
return data
end
---@param entityId string
---@param propertyId string
---@param data source
---@return void
local function expandSpecialsQualifiers( entityId, propertyId, data )
local statements = getBestStatements( entityId, propertyId )
for _, statement in pairs( statements ) do
populateDataFromSnaks( statement.qualifiers or {}, data, PROPERTY_MAP )
end
end
---Expand special types of references when additional data could be found in OTHER entity properties
---@param data source
---@return void
local function expandSpecials( data )
if not data.entityId then
return
end
if data.sourceId == 'Q36578' then
-- Gemeinsame Normdatei -- specified by P227
appendEntitySnaks( data.entityId, 'P227', data, 'part', { format = function(gnd ) return 'Record #' .. gnd; end } )
appendEntitySnaks( data.entityId, 'P227', data, 'url', { format = function(gnd ) return 'http://d-nb.info/gnd/' .. gnd .. '/'; end } )
data.year = '2012—2016'
expandSpecialsQualifiers( data.entityId, 'P227', data )
elseif data.sourceId == 'Q15222191' then
-- BNF -- specified by P268
appendEntitySnaks( data.entityId, 'P268', data, 'part', { format = function(id ) return 'Record #' .. id; end } )
appendEntitySnaks( data.entityId, 'P268', data, 'url', { format = function(id ) return 'http://catalogue.bnf.fr/ark:/12148/cb' .. id; end } )
expandSpecialsQualifiers( data.entityId, 'P268', data )
elseif data.sourceId == 'Q54919' then
-- VIAF -- specified by P214
appendEntitySnaks( data.entityId, 'P214', data, 'part', { format = function(id ) return 'Record #' .. id; end } )
appendEntitySnaks( data.entityId, 'P214', data, 'url', { format = function(id ) return 'https://viaf.org/viaf/' .. id; end } )
expandSpecialsQualifiers( data.entityId, 'P214', data )
else
-- generic property search
for _, sourceClaim in pairs( getBestStatements( data.sourceId, 'P1687' ) ) do
if sourceClaim.mainsnak.snaktype == 'value' then
local sourcePropertyId = sourceClaim.mainsnak.datavalue.value.id
for _, sourcePropertyClaim in pairs( getBestStatements( sourcePropertyId, 'P1630' ) ) do
if sourcePropertyClaim.mainsnak.snaktype == 'value' then
appendEntitySnaks( data.entityId, sourcePropertyId, data, 'url', {
format = function( id )
return mw.ustring.gsub( mw.ustring.gsub( sourcePropertyClaim.mainsnak.datavalue.value, '$1', id ), ' ', '%%20' )
end
} )
expandSpecialsQualifiers( data.entityId, sourcePropertyId, data )
break
end
end
end
end
end
-- do we have appropriate record in P1433 ?
local claims = findClaimsByValue( currentEntityId, 'P1343', data.sourceId )
if claims and #claims ~= 0 then
for _, claim in pairs( claims ) do
populateDataFromSnaks( claim.qualifiers, data, PROPERTY_MAP )
populateDataFromEntity( data.sourceId, data, PROPERTY_MAP )
end
end
end
---@param text string
---@param tip string
---@return string
local function toTextWithTip( text, tip )
return '<span title="' .. tip .. '" style="border-bottom: 1px dotted; cursor: help; white-space: nowrap">' .. text .. '</span>'
end
---@param lang string
---@param placeId string
---@return string
local function getPlaceName( placeId, lang )
-- ГОСТ Р 7.0.12—2011
if lang == 'ru' then
if placeId == 'Q649' then return toTextWithTip( 'М.', 'Москва' ); end
if placeId == 'Q656' then return toTextWithTip( 'СПб.', 'Санкт-Петербург' ); end
if placeId == 'Q891' then return toTextWithTip( 'Н. Новгород', 'Нижний Новгород' ); end
if placeId == 'Q908' then return toTextWithTip( 'Ростов н/Д.', 'Ростов-на-Дону' ); end
end
return nil
end
---@param data source
---@param lang string
---@return void
local function preprocessPlace( data, lang )
if not data.place then
return
end
---@type table<number, string>
local newPlace = {}
for index, place in pairs( data.place ) do
if place.id then
local newPlaceStr = getPlaceName( place.id, lang )
if newPlaceStr then
newPlace[ index ] = newPlaceStr
else
newPlace[ index ] = getLabel( place.id, lang )
end
else
newPlace[ index ] = place
end
end
data.place = newPlace
end
---@param entityId string
---@param lang string
---@param providedLabel string | nil
---@param options options
---@return string
local function getPersonNameAsLabel( entityId, lang, providedLabel, options )
-- would custom label provided we don't need to check entity at all
if not isEmpty( providedLabel ) then
return options.format( providedLabel )
end
if lang == 'mul' then
lang = i18nDefaultLanguage
end
---@type string | nil
local personName = getLabel( entityId, lang )
if isEmpty( personName ) then
return '\'\'(not translated to ' .. lang .. ')\'\''
end
if not isInstanceOf( entityId, 'Q5' ) then
return personName
end
return options.format( personName )
end
---@param entityId string
---@param lang string
---@param customLabel string | nil
---@param options options
---@return string
local function getPersonNameAsWikitext( entityId, lang, customLabel, options )
local personName = getPersonNameAsLabel( entityId, lang, customLabel, options )
local link = getElementLink( entityId, lang )
return wrapInUrl( link, personName )
end
---@param value value
---@param lang string
---@param options options
---@return string
local function getPeopleAsWikitext( value, lang, options )
if type( value ) == 'string' then
return options.format( value )
elseif type( value ) == 'table' then
if value.id then
-- this is link
if options.preferids then
return tostring( value.id )
else
if options.nolinks then
return getPersonNameAsLabel( value.id, lang, value.label, options )
else
return getPersonNameAsWikitext( value.id, lang, value.label, options )
end
end
end
local maxAuthors = 10 -- need some restrictions, as some publications have enormous amount of authors (e.g. 115 authors of Q68951544)
local resultList = {}
for _, tableValue in pairs( value ) do
local nextWikitext = getPeopleAsWikitext( tableValue, lang, options )
if not isEmpty( nextWikitext ) then
table.insert( resultList, nextWikitext )
if #resultList == maxAuthors + 1 then
-- keep one more to indicate that there are too many
break
end
end
end
local resultWikitext = ''
for i, wikitext in pairs( resultList ) do
if i == maxAuthors + 1 then
resultWikitext = resultWikitext .. ( i18nEtAl[ lang ] or i18nEtAlDefault )
break
end
if i ~= 1 then
resultWikitext = resultWikitext .. ', '
end
resultWikitext = resultWikitext .. wikitext
end
return resultWikitext
end
return '' -- options.format( '(unknown type)' )
end
---@param lang string
---@param data source
---@return string
local function generateAuthorLinks( lang, data )
local result = ''
if data.author then
result = getPeopleAsWikitext( data.author, lang, options_commas_authors )
result = '<i class="wef_low_priority_links">' .. result .. '</i> '
end
return result
end
---@param lang string
---@param data source
---@param conjunction string
---@param propertyName string
---@param urlPropertyName string?
---@return string
local function appendProperty( lang, data, conjunction, propertyName, urlPropertyName )
if not data[ propertyName ] then
return ''
end
local out
if urlPropertyName and data[ urlPropertyName ] then
out = wrapInUrl( data[ urlPropertyName ], asString( lang, data[ propertyName ], options_commas_nolinks ) )
else
out = asString( lang, data[ propertyName ], options_commas )
end
if not out or out == '' then
return ''
end
return conjunction .. out
end
---@param lang string
---@param data source
---@return string
local function appendTitle( lang, data )
local conjunction = ''
local result = ''
if data.part then
result = result .. appendProperty( lang, data, '', 'part', 'parturl' )
conjunction = ' // '
end
return result .. appendProperty( lang, data, conjunction, 'title', 'url' )
end
---@param lang string
---@return string
local function appendLanguage( lang )
if lang == i18nDefaultLanguage then
return ''
end
---@type { getRefHtml: ( fun( lang: string ): string ), list_ref: ( fun( frame: frame ): string ) }
local langs = require( 'Module:Languages' )
return langs.list_ref( p.currentFrame:newChild{ args = { lang } } )
end
---@param lang string
---@param data source
---@return string
local function appendSubtitle( lang, data )
return appendProperty( lang, data, ': ', 'subtitle', nil )
end
---@param lang string
---@param data source
---@return string
local function appendOriginalTitle( lang, data )
return appendProperty( lang, data, ' = ', 'originaltitle', nil )
end
---@param lang string
---@param data source
---@return string
local function appendPublication( lang, data )
if not data.publication then
return ''
end
local result = ' // ' .. asString( lang, data.publication.title, options_commas_it_short )
if data.publication.subtitle and data.publication.subtitle ~= '' then
result = result .. ': ' .. asString( lang, data.publication.subtitle, options_commas_it_short )
end
return result
end
---@param lang string
---@param data source
---@return string
local function appendEditor( lang, data )
if not data.editor and not data.translator then
return ''
end
local result = ' / '
if data.editor then
local prefix = i18nEditors[ lang ] or i18nEditors[ i18nDefaultLanguage ]
result = result .. prefix .. getPeopleAsWikitext( data.editor, lang, options_commas_responsible )
if data.translator then
result = result .. ', '
end
end
if data.translator then
local prefix = i18nTranslators[ lang ] or i18nTranslators[ i18nDefaultLanguage ]
result = result .. prefix .. getPeopleAsWikitext( data.translator, lang, options_commas_responsible )
end
return result
end
---@param lang string
---@param data source
local function appendEdition( lang, data )
return appendProperty( lang, data, ' — ', 'edition', nil )
end
---@param lang string
---@param data source
---@return string
local function appendPublicationData( lang, data )
if not data.place and not data.publisher and not data.year then
return ''
end
local result = ' — '
if data.place then
result = result .. asString( lang, data.place, options_commas_short )
if data.publisher or data.year then
result = result .. ': '
end
end
if data.publisher then
result = result .. asString( lang, data.publisher, options_commas_short )
if data.year then
result = result .. ', '
end
end
if data.year then
result = result .. asString( lang, data.year, options_commas )
end
result = result .. '.'
return result
end
---@param lang string
---@param data source
---@return string
local function appendVolumeAndIssue( lang, data )
if not data.volume and not data.issue then
return ''
end
local result = ' — '
local letter_vol = i18nVolume[ lang ] or i18nVolume[ i18nDefaultLanguage ]
local letter_iss = i18nIssue[ lang ] or i18nIssue[ i18nDefaultLanguage ]
if data.volume then
result = result .. appendProperty( lang, data, letter_vol .. ' ', 'volume', nil )
result = result ..appendProperty( lang, data, ', ' .. letter_iss .. ' ', 'issue', nil )
else
result = result .. appendProperty( lang, data, letter_iss .. ' ', 'issue', nil )
end
result = result .. '.'
return result
end
---@param lang string
---@param data source
---@return string
local function appendPages( lang, data )
if not data.pages then
return ''
end
local letter = i18nPages[ lang ] or i18nPages[ i18nDefaultLanguage ]
local strPages = asString( lang, data.pages, options_commas )
strPages = mw.ustring.gsub( strPages, '[-—]', '—' )
return ' — ' .. letter .. ' ' .. strPages .. '.'
end
---@param lang string
---@param data source
---@return string
local function appendNumberOfPages( lang, data )
if not data.numberOfPages then
return ''
end
local letter = i18nNumberOfPages[ lang ] or i18nNumberOfPages[ i18nDefaultLanguage ]
return appendProperty( lang, data, ' — ', 'numberOfPages', nil ) .. ' ' .. letter
end
---@param lang string
---@param data source
---@return string
local function appendBookSeries( lang, data )
if not data.bookSeries then
return ''
end
local result = appendProperty( lang, data, ' — (', 'bookSeries', nil )
if data.bookSeriesVolume or data.bookSeriesIssue then
result = result .. '; '
local letter_vol = i18nVolume[ lang ] or i18nVolume[ i18nDefaultLanguage ]
local letter_iss = i18nIssue[ lang ] or i18nIssue[ i18nDefaultLanguage ]
if data.bookSeriesVolume then
result = result .. appendProperty( lang, data, letter_vol .. ' ', 'bookSeriesVolume', nil )
result = result .. appendProperty( lang, data, ', ' .. letter_iss .. ' ', 'bookSeriesIssue', nil )
else
result = result .. appendProperty( lang, data, letter_iss .. ' ', 'bookSeriesIssue', nil )
end
end
result = result .. ')'
return result
end
---@param lang string
---@param data source
---@return string
local function appendTirage( lang, data )
if not data.tirage then
return ''
end
local tirageTemplate = i18nTirage[ lang ] or i18nTirage[ i18nDefaultLanguage ]
---@type options
local optionsTirage = {
separator = '; ',
conjunction = '; ',
format = function( _data ) return tostring( mw.ustring.format( tirageTemplate, _data ) ) end,
short = false,
nolinks = false,
preferids = false,
}
return ' — ' .. asString( lang, data.tirage, optionsTirage )
end
---@param lang string
---@param value string | nil
---@param options options
---@param prefix string?
---@return string
local function appendIdentifier( lang, value, options, prefix )
if not value then
return ''
end
return ' — ' .. ( prefix or '' ) .. asString( lang, value, options )
end
---@param result string
---@param lang string
---@param data source
---@return string
local function wrapSourceId( result, lang, data )
if not data.sourceId then
return result
end
local citeType = data.type and asString( lang, data.type, options_citetypes ) or 'citetype_unknown'
return '<span class="wikidata_cite ' .. citeType .. '" data-entity-id="' .. data.sourceId .. '">' .. result .. '</span>'
end
---@param data source
---@return string
local function appendAccessDate( data )
if not data.accessdate then
return ''
end
local date = getSingle( data.accessdate )
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local y, m, d = mw.ustring.match( date, pattern )
y, m, d = tonumber( y ), tonumber( m ), tonumber( d )
local date_str = ( d > 0 and ' ' .. tostring( d ) or '' )
.. ( m > 0 and ' ' .. monthGen[ m ] or '' )
.. ( y > 0 and ' ' .. tostring( y ) or '' )
return " <small>Проверено" .. date_str .. ".</small>"
end
---@param data source
---@param lang string
---@return void
local function populateUrl( data, lang )
if data.sourceId and not data.url then
local sitelink = getSitelink( data.sourceId, lang .. 'wikisource' )
if sitelink then
data.url = ':' .. lang .. ':s:' .. sitelink
end
end
end
---@param data source
---@return void
local function populateYear( data )
if not data.year and data.dateOfPublication then
local date = getSingle( data.dateOfPublication )
data.year = mw.ustring.sub( date, 2, 5 )
end
if not data.year and data.dateOfCreation then
local date = getSingle( data.dateOfCreation )
data.year = mw.ustring.sub( date, 2, 5 )
end
end
---@param data source
---@return void
local function populateTitle( data )
data.title = data.title or getSingle( data.url )
end
---@param data source
---@return string
local function renderSource( data )
local lang = getLangCode( data.lang ) or i18nDefaultLanguage
preprocessPlace( data, lang )
populateUrl( data, lang )
populateTitle( data )
if not data.title then
return ''
end
populateYear( data )
local result = generateAuthorLinks( lang, data )
result = result .. appendTitle( lang, data )
result = result .. appendLanguage( lang )
result = result .. appendSubtitle( lang, data )
result = result .. appendOriginalTitle( lang, data )
result = result .. appendPublication( lang, data )
result = result .. '<span class="wef_low_priority_links">'
result = result .. appendEditor( lang, data ) -- Might take current editor instead of actual. Use with caution
result = result .. appendEdition( lang, data )
result = result .. appendPublicationData( lang, data )
result = result .. appendVolumeAndIssue( lang, data )
result = result .. appendPages( lang, data )
result = result .. appendNumberOfPages( lang, data )
result = result .. appendBookSeries( lang, data )
result = result .. appendTirage( lang, data )
result = result .. appendIdentifier( lang, data.isbn, options_commas, 'ISBN ' )
result = result .. appendIdentifier( lang, data.issn, options_issn, 'ISSN ' )
result = result .. appendIdentifier( lang, data.doi, options_doi, nil )
result = result .. appendIdentifier( lang, data.pmid, options_pmid, nil )
result = result .. appendIdentifier( lang, data.arxiv, options_arxiv, nil )
result = result .. appendAccessDate( data )
result = result .. '</span>'
return wrapSourceId( result, lang, data )
end
---@param data source Данные в простом формате, согласованном с модулями формирования библиографического описания
---@param snaks snaks
---@return string | nil
local function renderReferenceImpl( data, snaks )
-- не показывать источники с "импортировано из"
if snaks.P143 then
return nil
end
-- забрать данные из reference
populateDataFromSnaks( snaks or {}, data, PROPERTY_MAP )
data.sourceId = getSingle( data.sourceId )
populateDataFromEntity( data.sourceId, data, PROPERTY_MAP )
expandSpecials( data )
populateSourceDataImpl( data.sourceId, data, PROPERTY_MAP )
expandPublication( data )
expandBookSeries( data )
if next( data ) == nil then
return nil
end
local rendered = renderSource( data )
if mw.ustring.len( rendered ) == 0 then
return nil
end
if data.ref then
local anchorValue = 'CITEREF' .. data.ref .. ( coalesce( { data[ 'ref-year' ], data.year } ) or '' )
rendered = '<span class="citation" id="' .. mw.uri.anchorEncode( anchorValue ) .. '">' .. rendered .. '</span>'
end
return rendered
end
---@param frame frame
---@param currentEntityId string | { id: string }
---@param reference table{ snaks: snaks }
---@return string | nil
function p.renderSource( frame, currentEntityId, reference )
reference = reference or { snaks = {} }
p.currentFrame = frame
local data = getFilledArgs( frame.args or {} )
populateDataFromSnaks( reference.snaks, data, PROPERTY_MAP )
data.sourceId = getSingle( data.sourceId )
if not currentEntityId then
data.entityId = mw.wikibase.getEntityIdForCurrentPage()
elseif type( currentEntityId ) == 'string' then
data.entityId = currentEntityId
elseif type( currentEntityId ) == 'table' and currentEntityId.id then
data.entityId = currentEntityId.id
end
---@type string
local rendered = renderReferenceImpl( data, reference.snaks or {} )
if not rendered then
return ''
end
return rendered
end
---@param frame frame
---@param currentEntityId string
---@param reference table
---@return string
function p.renderReference( frame, currentEntityId, reference )
local rendered = p.renderSource( frame, currentEntityId, reference )
if not rendered or rendered == '' then
return ''
end
-- Про выбор алгоритма хеширования см. [[Модуль:Hash]]. Знак подчёркивания в начале позволяет
-- исключить ошибку, когда имя сноски — чисто числовое значение, каковыми иногда бывают хеши.
return frame:extensionTag( 'ref', rendered, { name = '_' .. mw.hash.hashValue( 'fnv164', rendered ) } ) .. '[[Category:Википедия:Статьи с источниками из Викиданных]]'
end
---@param frame frame
---@return string | nil
function p.testPersonNameToAuthorName( frame )
return personNameToAuthorName( frame.args[ 1 ] )
end
---@param frame frame
---@return string | nil
function p.testPersonNameToResponsibleName( frame )
return personNameToResponsibleName( frame.args[ 1 ] )
end
return p
752a204827a41ecd6cf518bdb22da12718bca2ec
Модуль:WikidataSelectors
828
33
64
63
2025-01-25T21:00:17Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local i18n = {
["errors"] = {
["rank-not-valid"] = "Некорретное значение приоритета (rank)",
["cant-parse-condition"] = "Не удалось разобрать условие"
}
}
local validRanks = {
'best',
'preferred',
'normal',
'deprecated'
}
--[[
Internal function for error message
Input: key in errors table
Output: error message
]]
local function throwError( key )
error( i18n.errors[key] )
end
local p = {}
--[[
Load property and filter statements
Input: entityId, selector string
Output: filtered statements table
]]
function p.load( entityId, propertySelector )
local propertyId = mw.ustring.match( propertySelector, '^[Pp]%d+' )
if not propertyId then
return nil
end
propertyId = string.upper( propertyId )
local allStatements = {}
allStatements[ propertyId ] = mw.wikibase.getAllStatements( entityId, propertyId )
return p.filter( allStatements, propertySelector )
end
--[[
Parse selectors and filter statements
Input: statements table, selector string
Output: filtered statements table
]]
function p.filter( allClaims, propertySelector )
propertySelector = mw.text.trim( propertySelector )
-- Get property ID from selector
local propertyId = mw.ustring.match( propertySelector, '^[Pp]%d+' )
if not propertyId then
propertyId = ''
end
local initPos = #propertyId + 1
propertyId = string.upper( propertyId )
if ( not allClaims ) then
return nil
end
local allPropertyClaims = allClaims[propertyId]
if ( not allPropertyClaims ) then
return nil
end
-- Gathering rules
local rules = p.matchSelectors( propertySelector, initPos )
-- If there is no rank filter, than default rank is 'best'
local isRanked = false
for i, subRules in ipairs( rules ) do
for j, rule in ipairs( subRules ) do
if rule['type'] == 'rank' then
isRanked = true
break
end
end
end
if not isRanked then
table.insert( rules, 1, { { type = 'rank', value = 'best' } } )
end
-- Execute rules
allPropertyClaims = p.applyRules( allPropertyClaims, rules )
return allPropertyClaims
end
--[[
Match and gather selector rules
Input: string with selectors rules, start position
Output: rules table
]]
function p.matchSelectors( selectorsString, initPos )
local rules = {}
local rawRulePattern = '^%s*%[%s*[^%[%]]+%s*%]%s*'
local rulePattern = '^%s*%[%s*([^%[%]]+)%s*%]%s*$'
if not initPos then
initPos = 1
end
local rawRule = mw.ustring.match( selectorsString, rawRulePattern, initPos )
while rawRule do
initPos = initPos + #rawRule
rule = mw.ustring.match( rawRule, rulePattern )
rule = mw.text.trim( rule )
local subRules = mw.text.split( rule, '%s*,%s*' )
local commands = {}
local comm
for i, subRule in ipairs( subRules ) do
local isInversed = false
if mw.ustring.match( subRule, '^!' ) then
isInversed = true
subRule = mw.ustring.match( subRule, '^!%s*(.+)$' )
end
-- p123[1]
if mw.ustring.match( subRule, '^%d+$' ) then
table.insert( commands, {
type = 'position',
value = subRule,
inversed = isInversed
} )
-- p123[rank:preferred]
elseif mw.ustring.match( subRule, '^rank%s*:%s*(%a+)$' ) then
rank = mw.ustring.match( subRule, '^rank%s*:%s*(%a+)$' )
table.insert( commands, {
type = 'rank',
value = rank,
inversed = isInversed
} )
-- p123[language:xx]
elseif mw.ustring.match( subRule, '^language%s*:%s*([%a%-]+)$' ) then
value = mw.ustring.match( subRule, '^language%s*:%s*([%a%-]+)$' )
table.insert( commands, {
type = 'language',
value = value,
inversed = isInversed
} )
-- p123[language!:xx]
elseif mw.ustring.match( subRule, '^language%s*!:%s*([%a%-]+)$' ) then
value = mw.ustring.match( subRule, '^language%s*!:%s*([%a%-]+)$' )
table.insert( commands, {
type = 'language',
value = value,
inversed = not isInversed
} )
-- p123[min]
elseif mw.ustring.match( subRule, '^min$' ) then
table.insert( commands, { type = 'value_min' } )
-- p123[max]
elseif mw.ustring.match( subRule, '^max$' ) then
table.insert( commands, { type = 'value_max' } )
-- p123[min:p456]
elseif mw.ustring.match( subRule, '^min%s*:%s*[Pp]%d+$' ) then
value = mw.ustring.match( subRule, ':%s*([Pp]%d+)$' )
table.insert( commands, {
type = 'qualifier_min',
qualifier = value
} )
-- p123[max:p456]
elseif mw.ustring.match( subRule, '^max%s*:%s*[Pp]%d+$' ) then
value = mw.ustring.match( subRule, ':%s*([Pp]%d+)$' )
table.insert( commands, {
type = 'qualifier_max',
qualifier = value
} )
-- p123[unit:q789]
elseif mw.ustring.match( subRule, '^unit%s*:%s*[^%[%],:]+$' ) then
value = mw.ustring.match( subRule, ':%s*([^%[%],:]+)$' )
table.insert( commands, {
type = 'unit',
value = value,
inversed = isInversed
} )
-- p123[unit!:q789]
elseif mw.ustring.match( subRule, '^unit%s*!:%s*[^%[%],:]+$' ) then
value = mw.ustring.match( subRule, '!:%s*([^%[%],:]+)$' )
table.insert( commands, {
type = 'unit',
value = value,
inversed = not isInversed
} )
-- p123[p456]
elseif mw.ustring.match( subRule, '^[Pp]%d+$' ) then
qualifier = mw.ustring.match( subRule, '^[Pp]%d+' )
table.insert( commands, {
type = 'qualifier',
qualifier = qualifier,
value = nil,
inversed = isInversed
} )
-- p123[p456:q789]
elseif mw.ustring.match( subRule, '^[Pp]%d+%s*:%s*[^%[%],:]+$' ) then
qualifier = mw.ustring.match( subRule, '^([Pp]%d+)%s*:?' )
value = mw.ustring.match( subRule, ':%s*([^%[%],:]+)$' )
table.insert( commands, {
type = 'qualifier',
qualifier = qualifier,
value = value,
inversed = isInversed
} )
-- p123[p456!:q789]
elseif mw.ustring.match( subRule, '^[Pp]%d+%s*!:%s*[^%[%],:]+$' ) then
qualifier = mw.ustring.match( subRule, '^([Pp]%d+)%s*!:?' )
value = mw.ustring.match( subRule, '!:%s*([^%[%],:]+)$' )
table.insert( commands, {
type = 'qualifier',
qualifier = qualifier,
value = value,
inversed = not isInversed
} )
-- p123[q456]
elseif mw.ustring.match( subRule, '^[Qq]%d+$' ) then
value = mw.ustring.match( subRule, '^[Qq]%d+' )
table.insert( commands, {
type = 'value',
value = value,
inversed = isInversed
} )
else
throwError( 'cant-parse-condition' )
end
end
if #commands then
table.insert( rules, commands )
end
rawRule = mw.ustring.match( selectorsString, rawRulePattern, initPos )
end
return rules
end
--[[
Intercept statements with selector rules
Input: statements table, selector rules
Output: filtered statements table
]]
function p.applyRules( claims, rules )
for i, subRules in ipairs( rules ) do
local newClaims = {}
for j, rule in ipairs( subRules ) do
if rule['type'] == 'rank' then
table.insert( newClaims, p.filterByRank( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'language' then
table.insert( newClaims, p.filterByLanguage( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'unit' then
table.insert( newClaims, p.filterByUnit( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'position' then
table.insert( newClaims, p.filterByPosition( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'qualifier' then
table.insert( newClaims, p.filterByQualifier( claims, rule['qualifier'], rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'qualifier_min' then
table.insert( newClaims, p.filterUtterByQualifier( claims, rule['qualifier'], true ) )
elseif rule['type'] == 'qualifier_max' then
table.insert( newClaims, p.filterUtterByQualifier( claims, rule['qualifier'], false ) )
elseif rule['type'] == 'value' then
table.insert( newClaims, p.filterByValue( claims, rule['value'], rule['inversed'] ) )
elseif rule['type'] == 'value_min' then
table.insert( newClaims, p.filterUtter( claims, true ) )
elseif rule['type'] == 'value_max' then
table.insert( newClaims, p.filterUtter( claims, false ) )
end
end
claims = {}
--[[
Merge all claims
TODO: It's not good
]]
for j, newSubClaims in ipairs( newClaims ) do
for k, newClaim in ipairs( newSubClaims ) do
local isNew = true
for l, oldClaim in ipairs( claims ) do
if oldClaim['id'] == newClaim['id'] then
isNew = false
break
end
end
if isNew then
table.insert( claims, newClaim )
end
end
end
end
return claims
end
--[[
Filter statements by rank
Input: claims table, rank value, inversion
Output: filtered statements table
]]
function p.filterByRank( claims, rank, inversed )
if not inversed then
inversed = false
end
if not rank then
rank = 'best'
end
-- Check if rank value is valid
local isValidRank = false
for i, validRank in ipairs( validRanks ) do
if rank == validRank then
isValidRank = true
break
end
end
if not isValidRank then
throwError( 'rank-not-valid' )
end
-- Find the best rank
if rank == 'best' then
rank = 'normal' -- default rank (don't use deprecated even if it's no more claims)
-- If we have at least one preferred rank, mark it as best
for i, statement in pairs( claims ) do
if (statement.rank == 'preferred') then
rank = 'preferred'
break
end
end
end
local resultClaims = {};
for i, statement in pairs( claims ) do
if ( statement.rank == rank ) ~= inversed then
table.insert( resultClaims, statement )
end
end
return resultClaims
end
--[[
Filter statements by language of value
Input: claims table, language, inversion
Output: filtered statements table
]]
function p.filterByLanguage( claims, language, inversed )
if not inversed then
inversed = false
end
local resultClaims = {}
local mulStatement = {}
for i, statement in ipairs( claims ) do
isMatchLanguage = false
if statement['mainsnak']
and statement['mainsnak']['datavalue']
and statement['mainsnak']['datavalue']['value']
and statement['mainsnak']['datavalue']['value']['language'] then
if statement['mainsnak']['datavalue']['value']['language'] == language then
isMatchLanguage = true
end
if statement['mainsnak']['datavalue']['value']['language'] == 'mul' then
mulStatement = statement
end
end
if isMatchLanguage ~= inversed then
table.insert( resultClaims, statement )
end
end
if next(resultClaims) == nil and next(mulStatement) ~= nil then
-- if specific language is not found, but there is Q20923490 value
table.insert( resultClaims, mulStatement )
end
return resultClaims
end
--[[
Filter statements by unit of value
Input: claims table, unit, inversion
Output: filtered statements table
]]
function p.filterByUnit( claims, unit, inversed )
if not inversed then
inversed = false
end
unit = 'http://www.wikidata.org/entity/' .. string.upper( unit )
local resultClaims = {}
for i, statement in ipairs( claims ) do
isMatchUnit = false
if statement['mainsnak']
and statement['mainsnak']['datavalue']
and statement['mainsnak']['datavalue']['value']
and statement['mainsnak']['datavalue']['value']['unit']
and statement['mainsnak']['datavalue']['value']['unit'] == unit then
isMatchUnit = true
end
if isMatchUnit ~= inversed then
table.insert( resultClaims, statement )
break
end
end
return resultClaims
end
--[[
Filter statements by position
Input: claims table, position, inversion
Output: filtered statements table
]]
function p.filterByPosition( claims, position, inversed )
if not inversed then
inversed = false
end
local resultClaims = {};
for statementPosition, statement in ipairs( claims ) do
if ( statementPosition == tonumber( position ) ) ~= inversed then
table.insert( resultClaims, statement )
break
end
end
return resultClaims
end
--[[
Filter statements by qualifier existance or it's value
Input: claims table, ID of qualifier's property, qualifier's value, inversion
Output: filtered statements table
]]
function p.filterByQualifier( claims, qualifierId, value, inversed )
if not inversed then
inversed = false
end
qualifierId = string.upper( qualifierId )
local resultClaims = {}
for i, statement in ipairs( claims ) do
if statement['qualifiers'] and statement['qualifiers'][qualifierId] then
if value == nil then
if ( #statement['qualifiers'][qualifierId] > 0 ) ~= inversed then
table.insert( resultClaims, statement )
end
else
local isQualifierFound = false
for j, qualifier in ipairs( statement['qualifiers'][qualifierId] ) do
if qualifier['datavalue'] then
local qualifierValue = qualifier['datavalue']['value']
if qualifier['datavalue']['type'] == 'wikibase-entityid' then
qualifierValue = qualifierValue.id
value = string.upper( value )
end
if qualifierValue == value then
isQualifierFound = true
break
end
end
end
if isQualifierFound ~= inversed then
table.insert( resultClaims, statement )
end
end
elseif inversed then
table.insert( resultClaims, statement )
end
end
return resultClaims
end
--[[
Filter statements by it's values
Input: claims table, value, inversed
Output: filtered statements table
]]
function p.filterByValue( claims, value, inversed )
inversed = inversed or false
local resultClaims = {}
for i, statement in ipairs( claims ) do
local statementValue
if statement['mainsnak']
and statement['mainsnak']['datavalue']
and statement['mainsnak']['datavalue']['type']
then
statementValue = statement['mainsnak']['datavalue']['value']
if statement['mainsnak']['datavalue']['type'] == 'quantity' then
statementValue = statementValue.amount
end
if statement['mainsnak']['datavalue']['type'] == 'time' then
statementValue = statementValue.time
end
if statement['mainsnak']['datavalue']['type'] == 'wikibase-entityid' then
statementValue = statementValue.id
value = string.upper( value )
end
end
if ( statementValue == value ) ~= inversed then
table.insert( resultClaims, statement )
end
end
return resultClaims
end
--[[
Find a statement with minimum or maximum value
Input: claims table, asc, inversed
Output: filtered statements table
]]
function p.filterUtter( claims, asc, inversed )
local resultValue = nil
for i, statement in ipairs( claims ) do
local statementValue
if statement['mainsnak'] and
statement['mainsnak']['datavalue'] and
statement['mainsnak']['datavalue']['type']
then
statementValue = statement['mainsnak']['datavalue']['value']
if statement['mainsnak']['datavalue']['type'] == 'quantity' then
statementValue = statementValue.amount
end
if statement['mainsnak']['datavalue']['type'] == 'time' then
statementValue = statementValue.time
end
if statement['mainsnak']['datavalue']['type'] == 'wikibase-entityid' then
statementValue = statementValue.id
end
if not resultValue or ( statementValue < resultValue ) == asc then
resultValue = statementValue
end
end
end
mw.logObject( resultValue, 'resultValue' )
return p.filterByValue( claims, resultValue, inversed )
end
--[[
Find a statement with minimum or maximum qualifier value
Input: claims table, qualifierId, asc
Output: filtered statements table
]]
function p.filterUtterByQualifier( claims, qualifierId, asc )
qualifierId = string.upper( qualifierId )
local resultValue = nil
local resultStatement = nil
for i, statement in ipairs( claims ) do
if not statement['qualifiers'] and not statement['qualifiers'][qualifierId] then
if resultStatement == nil then
resultStatement = statement
end
else
for _, qualifier in ipairs( statement['qualifiers'][qualifierId] ) do
if qualifier['datavalue'] then
local qualifierValue = qualifier['datavalue']['value']
if qualifier['datavalue']['type'] == 'quantity' then
qualifierValue = qualifierValue.amount
end
if qualifier['datavalue']['type'] == 'time' then
qualifierValue = qualifierValue.time
end
if qualifier['datavalue']['type'] == 'wikibase-entityid' then
qualifierValue = qualifierValue.id
end
if not resultValue or ( qualifierValue < resultValue ) == asc then
resultStatement = statement
resultValue = qualifierValue
end
end
end
end
end
return { resultStatement }
end
return p
0bdff3a63bf171160cdec5c966211fbbf3003880
Модуль:Infobox
828
35
68
67
2025-01-25T21:00:18Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local p = {};
local yesno = require('Module:Yesno')
local function _renderLine( frame, args, i )
if args[ 'заголовок' .. i ] and args[ 'заголовок' .. i ] == '-' then
return ''
elseif args[ 'заголовок' .. i ] and args[ 'заголовок' .. i ] ~= '' then
local style = ( args[ 'стиль_заголовков' ] or '' ) .. ( args[ 'стиль_заголовка' .. i ] or '' );
local class = ( args[ 'класс' .. i ] or '' );
return '\n<tr>\n<th colspan="2" scope="colgroup" class="infobox-header ' .. class .. '" style="' .. style .. '">' ..
args[ 'заголовок' .. i ] ..
'</th>\n</tr>';
end
if args[ 'блок' .. i ] and args[ 'блок' .. i ] ~= '' then
return args[ 'блок' .. i ];
end
local text = args[ 'текст' .. i ] or '';
if args[ 'викиданные' .. i ] and args[ 'викиданные' .. i ] ~= '' then
text = frame:expandTemplate{ title = 'Wikidata', args = {
args[ 'викиданные' .. i ],
text,
from = args[ 'from' ] or ''
} };
end
if text ~= '' then
local label = args[ 'метка' .. i ] or '';
local class = args[ 'класс' .. i ] or '';
if string.find(class, 'noplainlist') == nil and string.find(class, 'nofirstlevel') == nil then
class = class .. ' plainlist';
end
if class ~= '' then
class = ' class="' .. class .. '"';
end
local style = ( args[ 'стиль_текстов' ] or '' ) .. ( args[ 'стиль_текста' ] or '' ) .. ( args[ 'стиль_текста' .. i ] or '' );
if label == '' then
style = 'text-align:center;' .. style;
end
if style ~= '' then
style = ' style="' .. style .. '"';
end
if label ~= '' then
local labelClass = args[ 'класс_меток' ] or '';
if string.find(labelClass, 'noplainlist') == nil and string.find(labelClass, 'nofirstlevel') == nil then
labelClass = labelClass .. ' plainlist';
end
if labelClass ~= '' then
labelClass = ' class="' .. labelClass .. '"';
end
local labelStyle = ( args[ 'стиль_меток' ] or '' ) .. ( args[ 'стиль_метки' .. i ] or '' );
if labelStyle ~= '' then
labelStyle = ' style="' .. labelStyle .. '"';
end
return '\n<tr>\n<th scope="row"' .. labelClass .. labelStyle .. '>' .. label .. '</th>' ..
'\n<td' .. class .. style .. '>\n' .. text .. '</td>\n</tr>';
end
return '\n<tr>\n<td colspan="2"' .. class .. style .. '>\n' .. text .. '</td>\n</tr>';
end
return '';
end
local function maxNumber ( args )
local maxNumber = 0
for argName, _ in pairs(args) do
local argNumber = mw.ustring.match(argName, '^[^0-9]+([0-9]+)$')
if argNumber and tonumber(argNumber) > maxNumber then
maxNumber = tonumber(argNumber)
end
end
return maxNumber
end
function p.renderLine( frame )
local args = frame:getParent().args;
return _renderLine(frame, args, '')
end
function p.renderLines( frame )
local args = frame:getParent().args;
local res = ''
local header, text = '', ''
local autoHeaders = yesno(args [ 'автозаголовки' ] or 'false', false)
for i = 1, maxNumber(args) do
if args[ 'заголовок' .. i ] and args[ 'заголовок' .. i ] ~= '' then
if text ~= '' or not autoHeaders then
res = res .. header .. text
end
header, text = _renderLine(frame, args, i), ''
else
text = text .. _renderLine(frame, args, i)
end
end
if text ~= '' or not autoHeaders then
res = res .. header .. text
end
return res
end
return p;
c830c997bd3d15923f347277e3b0ae71b7ba917e
Модуль:Transclude
828
36
70
69
2025-01-25T21:00:19Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local p={}
-- Вызывает внутренний шаблон с аргументами объемлющего шаблона
function p.call(frame)
local template = frame.args[1]
local args = frame:getParent().args
return frame:expandTemplate{ title=template, args=args }
end
-- Общая реализация для forall и call
local function forallImpl(args, separator, conjunction, func)
-- нумерованные ключи из args
local keys = {}
-- перебор в произвольном порядке, даже для нумерованных ключей
for key, value in pairs(args) do
if type(key) == 'number' and value and value ~= '' then
table.insert(keys, key)
end
end
table.sort(keys)
local results = {}
for _, key in ipairs(keys) do
local value = func(args[key])
table.insert(results, value)
end
return mw.text.listToText(results, separator, conjunction)
end
-- Вызывает внутренний шаблон, передавая ему нумерованные параметры объемлющего шаблона по-одному
function p.forall(frame)
local template = frame.args[1]
local separator = frame.args.separator or ''
local conjunction = frame.args.conjunction or separator
local args = frame:getParent().args
local func = function(value)
return frame:expandTemplate{ title = template, args = {value} } -- или другой frame?
end
return forallImpl(args, separator, conjunction, func)
end
-- Берёт нумерованные аргументы объемлющего шаблона и склеивает их в единую строку
function p.join(frame)
local separator = frame.args[1] or ''
local conjunction = frame.args[2] or separator
local args = frame:getParent().args
local func = function(value)
return value
end
return forallImpl(args, separator, conjunction, func)
end
-- Служебная функция: удаляет дубликаты из отсортированного массива с нумерованными индексами
local function deleteDuplicates(args)
local res = {}
for key, value in pairs(args) do
if args[key+1] ~= value then
table.insert(res, value)
end
end
return res
end
-- Вызывает внутренний шаблон несколько раз, передавая в него блоки аргументов объемлющего шаблона
function p.npc(frame)
local args = frame:getParent().args
local templateFrame = frame:getParent()
local template = frame.args[1]
-- определение, блоки аргументов с какими номерами нужны:
-- если в объемлющем шаблоне есть "параметр12" и в вызове модуля есть "параметр", то вызывается 12-й блок
local nums = {}
for key, _ in pairs(args) do
local main, num = string.match(key, '^(.-)%s*(%d*)$')
num = tonumber(num)
-- учитывать "параметр12", только если задано "параметр"
if num and frame.args[main] then
table.insert(nums, num)
end
end
table.sort(nums)
nums = deleteDuplicates(nums)
-- проходить по нужным номерам блоков по возрастанию и однократно
-- подставлять в шаблон:
-- 1. общие аргументы данного модуля
-- 2. аргументы объемлющего шаблона вида "параметр12" как "параметр" в 12-й блок
local results = {}
for _, blockNum in ipairs(nums) do
-- общие аргументы модуля, которые передаются в каждый блок
local blockArgs = mw.clone(frame.args)
-- metatable ломает expandTemplate
setmetatable(blockArgs, nil)
for key, value in pairs(args) do
local main, num = string.match(key, '^(.-)%s*(%d*)$')
num = tonumber(num)
-- передавать "параметр12" как "параметр" в 12-й блок, только если есть "параметр" в вызове модуля
if blockNum == num and frame.args[main] then
blockArgs[main] = value
end
end
local blockText = templateFrame:expandTemplate{ title=template; args=blockArgs }
table.insert(results, blockText)
end
return table.concat(results)
end
-- Действует аналогично forall по числовой переменной, изменяющейся (по умолчанию, от 1) до f.args[2].
function p.cycle(f)
local tf,ac,op=f:getParent(), {}, f.args.output or 'inline';
local sep='';
if op == 'newline' then
sep='\n';
end
for p,k in pairs(f.args) do
if type(p)=='number' then
if p>2 then ac[p-1]=k end
else ac[p]=k
end
end
local s,fh = f.args[2]:match('^%s*(%-?%d+)%s*%.%.') or 1,
f.args[2]:match('%.%.%s*(%S.*)%s*$') or f.args[2] or '';
fh=tonumber(fh) or fh:match('^%s*(.-)%s*$');
s=tonumber(s);
local acr={};
if not s then error('Начало цикла «'..s..'» — не число') end
local function dc(order)
local r=tf:expandTemplate{ title=f.args[1]; args={s,unpack(ac)} }
if order == 'desc' then
s=s-1;
else
s=s+1;
end
if r~='' then table.insert(acr,r); return r end
end
if type(fh)=='number' then
if fh > s then
while s<=fh do dc('asc') end
else
while s>=fh do dc('desc') end
end
elseif fh~='' then
while tf:expandTemplate{ title=fh; args={s,unpack(ac)} } do dc('asc') end
else
while dc('asc') do end
end
return table.concat(acr, sep)
end
return p
c17cfab4cebc23157f5ab8d18c7e4f5c273bfa59
Шаблон:Replace
10
37
72
71
2025-01-25T21:00:19Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{safesubst:<noinclude />#invoke:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|plain={{{plain|true}}}|count={{{count|}}}}}<noinclude>
{{doc}}
</noinclude>
7752c3c70ae8c46a89a0808aa282956866dbba5b
Шаблон:Delink
10
38
74
73
2025-01-25T21:00:19Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:delink|delink}}<noinclude>
{{doc}}
</noinclude>
dbac86e53b946e60d5b6236381e8c31858e79ee5
Модуль:Delink
828
39
76
75
2025-01-25T21:00:20Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- This module de-links most wikitext.
require("strict")
local yesno = require("Module:Yesno")
local p = {}
local getArgs
local function delinkReversePipeTrick(s)
if s:match("^%[%[|.*[|\n]") then -- Check for newlines or multiple pipes.
return s
end
return s:match("%[%[|(.*)%]%]")
end
local function delinkPipeTrick(s)
-- We need to deal with colons, brackets, and commas, per [[Help:Pipe trick]].
-- First, remove the text before the first colon, if any.
if s:match(":") then
s = s:match("%[%[.-:(.*)|%]%]")
-- If there are no colons, grab all of the text apart from the square brackets and the pipe.
else
s = s:match("%[%[(.*)|%]%]")
end
-- Next up, brackets and commas.
if s:match("%(.-%)$") then -- Brackets trump commas.
s = s:match("(.-) ?%(.-%)$")
elseif s:match(",") then -- If there are no brackets, display only the text before the first comma.
s = s:match("(.-),.*$")
end
return s
end
-- Return wikilink target |wikilinks=target
local function getDelinkedTarget(s)
local result = s
-- Deal with the reverse pipe trick.
if result:match("%[%[|") then
return delinkReversePipeTrick(result)
end
result = mw.uri.decode(result, "PATH") -- decode percent-encoded entities. Leave underscores and plus signs.
result = mw.text.decode(result, true) -- decode HTML entities.
-- Check for bad titles. To do this we need to find the
-- title area of the link, i.e. the part before any pipes.
local target_area
if result:match("|") then -- Find if we're dealing with a piped link.
target_area = result:match("^%[%[(.-)|.*%]%]")
else
target_area = result:match("^%[%[(.-)%]%]")
end
-- Check for bad characters.
if mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") and mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") ~= "?" then
return s
end
return target_area
end
local function getDelinkedLabel(s)
local result = s
-- Deal with the reverse pipe trick.
if result:match("%[%[|") then
return delinkReversePipeTrick(result)
end
result = mw.uri.decode(result, "PATH") -- decode percent-encoded entities. Leave underscores and plus signs.
result = mw.text.decode(result, true) -- decode HTML entities.
-- Check for bad titles. To do this we need to find the
-- title area of the link, i.e. the part before any pipes.
local target_area
if result:match("|") then -- Find if we're dealing with a piped link.
target_area = result:match("^%[%[(.-)|.*%]%]")
else
target_area = result:match("^%[%[(.-)%]%]")
end
-- Check for bad characters.
if mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") and mw.ustring.match(target_area, "[%[%]<>{}%%%c\n]") ~= "?" then
return s
end
-- Check for categories, interwikis, and files.
local colon_prefix = result:match("%[%[(.-):.*%]%]") or "" -- Get the text before the first colon.
local ns = mw.site.namespaces[colon_prefix] -- see if this is a known namespace
if mw.language.isKnownLanguageTag(colon_prefix) or (ns and (ns.canonicalName == "File" or ns.canonicalName == "Category")) then
return ""
end
-- Remove the colon if the link is using the [[Help:Colon trick]].
if result:match("%[%[:") then
result = "[[" .. result:match("%[%[:(.*%]%])")
end
-- Deal with links using the [[Help:Pipe trick]].
if mw.ustring.match(result, "^%[%[[^|]*|%]%]") then
return delinkPipeTrick(result)
end
-- Find the display area of the wikilink
if result:match("|") then -- Find if we're dealing with a piped link.
result = result:match("^%[%[.-|(.+)%]%]")
-- Remove new lines from the display of multiline piped links,
-- where the pipe is before the first new line.
result = result:gsub("\n", "")
else
result = result:match("^%[%[(.-)%]%]")
end
return result
end
local function delinkURL(s)
-- Assume we have already delinked internal wikilinks, and that
-- we have been passed some text between two square brackets [foo].
-- If the text contains a line break it is not formatted as a URL, regardless of other content.
if s:match("\n") then
return s
end
-- Check if the text has a valid URL prefix and at least one valid URL character.
local valid_url_prefixes = {"//", "http://", "https://", "ftp://", "gopher://", "mailto:", "news:", "irc://"}
local url_prefix
for _ ,v in ipairs(valid_url_prefixes) do
if mw.ustring.match(s, '^%[' .. v ..'[^"%s].*%]' ) then
url_prefix = v
break
end
end
-- Get display text
if not url_prefix then
return s
end
s = s:match("^%[" .. url_prefix .. "(.*)%]") -- Grab all of the text after the URL prefix and before the final square bracket.
s = s:match('^.-(["<> ].*)') or "" -- Grab all of the text after the first URL separator character ("<> ).
s = mw.ustring.match(s, "^%s*(%S.*)$") or "" -- If the separating character was a space, trim it off.
local s_decoded = mw.text.decode(s, true)
if mw.ustring.match(s_decoded, "%c") then
return s
end
return s_decoded
end
local function delinkLinkClass(text, pattern, delinkFunction)
if type(text) ~= "string" then
error("Attempt to de-link non-string input.", 2)
end
if type(pattern) ~= "string" or mw.ustring.sub(pattern, 1, 1) ~= "^" then
error('Invalid pattern detected. Patterns must begin with "^".', 2)
end
-- Iterate over the text string, and replace any matched text. using the
-- delink function. We need to iterate character by character rather
-- than just use gsub, otherwise nested links aren't detected properly.
local result = ""
while text ~= "" do
-- Replace text using one iteration of gsub.
text = mw.ustring.gsub(text, pattern, delinkFunction, 1)
-- Append the left-most character to the result string.
result = result .. mw.ustring.sub(text, 1, 1)
text = mw.ustring.sub(text, 2, -1)
end
return result
end
function p._delink(args)
local text = args[1] or ""
if yesno(args.markers) == true then
text = mw.text.killMarkers(text) -- [[Help:Strip markers]]
end
if yesno(args.refs) == true then
-- Remove any [[Help:Strip markers]] representing ref tags. In most situations
-- this is not a good idea - only use it if you know what you are doing!
text = mw.ustring.gsub(text, "UNIQ%w*%-ref%-%d*%-QINU", "")
end
if not (yesno(args.comments) == false) then
text = text:gsub("<!%-%-.-%-%->", "") -- Remove html comments.
end
if not (yesno(args.wikilinks) == false) and args.wikilinks ~= "target" then
-- De-link wikilinks and return the label portion of the wikilink.
text = delinkLinkClass(text, "^%[%[.-%]%]", getDelinkedLabel)
elseif args.wikilinks == "target" then
-- De-link wikilinks and return the target portions of the wikilink.
text = delinkLinkClass(text, "^%[%[.-%]%]", getDelinkedTarget)
end
if not (yesno(args.urls) == false) then
text = delinkLinkClass(text, "^%[.-%]", delinkURL) -- De-link URLs.
end
if not (yesno(args.whitespace) == false) then
-- Replace single new lines with a single space, but leave double new lines
-- and new lines only containing spaces or tabs before a second new line.
text = mw.ustring.gsub(text, "([^\n \t][ \t]*)\n([ \t]*[^\n \t])", "%1 %2")
text = text:gsub("[ \t]+", " ") -- Remove extra tabs and spaces.
end
return text
end
function p.delink(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
return p._delink(getArgs(frame, {wrappers = 'Template:Delink'}))
end
return p
eb6cae0d369f288b0b1600633d9bf7874cefdcbc
Модуль:URL
828
40
78
77
2025-01-25T21:00:20Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
function startsWith( source, substring )
if mw.ustring.len( substring ) > mw.ustring.len( source ) then
return false
end
return mw.ustring.sub( source, 1, mw.ustring.len( substring ) ) == substring
end
p = {}
function formatUrlImpl( source, title, length )
local scheme, host, path
local postfix = ''
local arg1, arg2 = source, title
local isTestPage = mw.title.getCurrentTitle().prefixedText == 'Модуль:URL'
-- Две квадратные скобки подряд — [[вики-ссылка]] вместо [ссылки] — возвращаем вход как есть.
if string.find( arg1, "[[", 1, true ) then
local result = arg1
if not isTestPage then
result = result .. '[[Категория:Википедия:Статьи с вики-ссылкой, переданной в Модуль:URL]]'
if arg2 then
-- Если есть arg2, а мы распарсить ссылку не смогли, и значит заменить title не сможем корректно, это есть ошибка.
result = result .. '[[Категория:Википедия:Статьи с ошибочной работой Модуль:URL]]'
end
end
return result
end
-- Более одной квадратной скобки — скорее всего, задано более одного URL — тоже возвращаем как есть.
if select(2, string.gsub( arg1, "%[", "" )) > 1 then
local result = arg1
if not isTestPage then
result = result .. '[[Категория:Википедия:Статьи со сложным входом в Модуль:URL]]'
if arg2 then
-- Если есть arg2, а мы распарсить ссылку не смогли, и значит заменить title не сможем корректно, это есть ошибка.
result = result .. '[[Категория:Википедия:Статьи с ошибочной работой Модуль:URL]]'
end
end
return result
end
source = mw.text.trim( source, "%[%] " )
local titleDelimeterPosition = mw.ustring.find( source, " ", 1 )
if titleDelimeterPosition then
if not title or title == "" then
title = mw.ustring.sub( source, titleDelimeterPosition + 1 )
local postfixDelimeterPosition = mw.ustring.find( title, "%]", 1 )
if postfixDelimeterPosition then
postfix = mw.ustring.sub( title, postfixDelimeterPosition + 1 )
title = mw.ustring.sub( title, 1, postfixDelimeterPosition - 1 )
end
end
source = mw.ustring.sub( source, 1, titleDelimeterPosition - 1 )
end
local hostStartPosition
local schemeDelimeterPosition = mw.ustring.find( source, "://", 1, true )
if schemeDelimeterPosition then
scheme = mw.ustring.sub( source, 1, schemeDelimeterPosition + 2)
hostStartPosition = schemeDelimeterPosition + 3
elseif mw.ustring.find( source, "^//", 1 ) then
scheme = "//"
hostStartPosition = 3
elseif mw.ustring.find( source, "^mailto:", 1 ) then
scheme = "mailto:"
hostStartPosition = 8
elseif mw.ustring.find( source, "@", 1 ) then
scheme = "mailto:"
source = scheme .. source
hostStartPosition = 8
else
scheme = "http://"
source = scheme .. source
hostStartPosition = 8
end
if title then
local finds = mw.ustring.find( arg1, "[", 1, true )
if titleDelimeterPosition and finds and finds > titleDelimeterPosition + 1 then
-- Если titleDelimeterPosition промазал мимо скобки и нашел пробел раньше неё, к примеру "a [b c]",
-- то свернуть всю нашу хиромантию и выдать первый аргумент без изменений.
if arg2 == nil then
return arg1 .. (isTestPage and '' or '[[Категория:Википедия:Статьи со сложным входом в Модуль:URL]]')
-- Если есть arg2, а мы распарсить ссылку не смогли, и значит заменить title не сможем корректно, это есть ошибка.
-- С другой стороны, если arg2 нет, а arg1 очень сложный, то возможно это нормальный ход вещей,
-- и на вход в модуль дана уже очень сильно оформленная ссылка.
else
return arg1 .. (isTestPage and '' or '[[Категория:Википедия:Статьи с ошибочной работой Модуль:URL]]')
end
end
return '[' .. source .. ' ' .. title .. ']' .. postfix
end
local hostDelimeterPosition = mw.ustring.find( source, "/", hostStartPosition, true )
if hostDelimeterPosition then
host = mw.ustring.sub( source, hostStartPosition, hostDelimeterPosition - 1 )
if hostDelimeterPosition == mw.ustring.len( source ) then
path = nil
else
path = mw.ustring.sub( source, hostDelimeterPosition + 1 )
end
else
host = mw.ustring.sub( source, hostStartPosition )
end
-- post-split format options
if startsWith( host, 'www.' ) then
host = mw.ustring.sub( host, 5 )
end
host = mw.language.new( 'en' ):lc( host )
if path and path ~= '' and path ~= '/' then
local title = host .. '/' .. path
if length and #title > length then
title = host .. '/' .. mw.ustring.sub( path, 1, length - #title - 2 ) .. '…'
end
return '[' .. source .. ' ' .. title .. ']' .. postfix
else
return '[' .. source .. ' ' .. host .. ']' .. postfix
end
end
function p.formatUrl( frame )
local url = frame.args[1] or ''
local title = frame.args[2] or ''
local length = frame.args['length'] and tonumber( frame.args['length'] )
url = mw.text.trim( url )
title = mw.text.trim( title )
if url == '' then
return nil
end
if title == '' then
title = nil
end
return formatUrlImpl( url, title, length )
end
function p.formatUrlSingle( context, options, url )
url = mw.text.trim( url )
if url == '' then
return nil
end
local title = nil
if ( options['text'] and options['text'] ~= '' ) then
title = options['text']
end
local length = options['length'] and tonumber( options['length'] )
return formatUrlImpl( url, title, length )
end
return p
a991f879e135a472238c7f589e8d20d92a856d4d
Шаблон:Флагификация
10
41
80
79
2025-01-25T21:00:21Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#if: {{{1|}}}
| {{#switch: {{str left|{{{1|}}}|1}}
| [ | < | { = [[Категория:Википедия:Страницы с неверным параметром шаблона Флагификация]]
| #default = {{Флагификация/{{{1|}}}
| Флагификация/флагификация
| variant = {{{variant|{{{2|}}}}}}
| размер = {{{размер|}}}
}}
}}
}}<noinclude>{{doc}}</noinclude>
46f4b3bb9842eaf2c75057227b1b76b565563be5
Шаблон:Str left
10
42
82
81
2025-01-25T21:00:21Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>padleft:|{{{2|1}}}|{{{1|}}}}}<noinclude>
{{doc}}
</noinclude>
c1f57b63826f4d455dcaec8d2c24a2b8268f42ec
Шаблон:Флагификация/флагификация
10
43
84
83
2025-01-25T21:00:21Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<span class="nowrap" data-sort-value="{{{shortname alias|{{{alias}}}}}}"><span class="flagicon">[[File:{{{flag alias-{{{variant}}}|{{{flag alias}}}}}}|class=noresize|link=|alt=|{{#if: {{{размер|}}} | {{{размер}}} | 22x20px }}|{{{border-{{{variant}}}|{{{border|border}}}}}}]]</span> [[{{{alias}}}|<span class="wrap">{{{shortname alias-{{{variant}}}|{{{shortname alias|{{{alias}}}}}}}}}</span>]]</span><noinclude>{{doc}}</noinclude>
8403cde4528b4d7df313d2e82aeb40b0bb66c2c2
Шаблон:Карточка/имя
10
44
86
85
2025-01-25T21:00:21Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#if:{{{1|}}}|{{{1}}}|{{сначала имя|{{PAGENAME}}}}}}<noinclude>
{{doc}}
</noinclude>
c2c97d1196f5c50a2ec1aa866cd4004526a32383
Шаблон:Карточка/оригинал имени
10
45
88
87
2025-01-25T21:00:22Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{wikidata|p1559[language!:ru]|{{{1|}}}|before={{{before|}}}|separator=<br>|conjunction=<br>|monolingualLangTemplate={{{monolingualLangTemplate|lang}}}|from={{{from|}}}}}<!--
-->{{#if:{{NAMESPACE}}||{{#if:{{{1|}}}|{{#ifeq:{{#invoke:String|find|{{{1|}}}|span}}|0|[[Категория:Википедия:Статьи с оригиналом имени без шаблона lang-XX]]}}}}}}<noinclude>{{doc}}</noinclude>
a294e3f7f61c5206ca5671b72e21804d7a32fcbc
Шаблон:Wikidata/p569
10
46
90
89
2025-01-25T21:00:22Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#switch:{{{1|}}}|-=|={{#invoke:Wikidata|formatStatements|property=p569|claim-module=Wikidata/date|claim-function=formatDateOfBirthClaim|nocat={{{nocat|}}}{{NAMESPACE}}|suppressAge={{{suppress age|}}}}}|{{#invoke:Infocards|dateOfBirth|{{{1|}}}|{{{2|}}}|suppressAge={{wikidata|P570|plain=true}}{{{suppress age|}}}|nocat={{{nocat|}}}{{NAMESPACE}}}}}}<noinclude>{{doc}}</noinclude>
9643ab18fcd322831b72e38658b58c6b94a914e2
Шаблон:Wikidata/p570
10
47
92
91
2025-01-25T21:00:22Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#switch:{{{1|}}}|-=|={{#invoke:Wikidata|formatStatements|property=p570|claim-module=Wikidata/date|claim-function=formatDateOfDeathClaim|nocat={{{nocat|}}}{{NAMESPACE}}}}|{{#invoke:Infocards|dateOfDeath|{{{2|}}}|{{{1|}}}|nocat={{{nocat|}}}{{NAMESPACE}}}}}}<noinclude>{{doc}}</noinclude>
a51af6d007d156cfeacb13a0a4a7471da7d4ed22
Шаблон:Nobr
10
48
94
93
2025-01-25T21:00:23Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly><span class="nowrap">{{{1}}}</span></includeonly><noinclude>
{{doc}}
<!-- Пожалуйста, добавляйте категории и интервики на страницу документации! -->
</noinclude>
989c6f164ed3a8543e916c8f1746ba1ab94fb068
Шаблон:Wikidata gender switch
10
49
96
95
2025-01-25T21:00:23Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#switch: {{wikidata|p21|{{lc:{{delink|{{{1|}}}}}}}|plain=true|from={{{from|}}}}}
| 1 | f | fem | female | feminine | ж | жен | женский | женский пол | транс-женщина | Q6581072 | Q1052281 | Q43445 = {{{2}}}
| m | male | masculine | м | муж | мужской | мужской пол | транс-мужчина | Q6581097 | Q2449503 | Q44148 = {{{3}}}
| #default = {{#if:{{{4|}}}|{{{4}}}|{{{3}}}}}
}}<noinclude>
{{doc}}
</noinclude>
24ccdd5a8702a7028386e9b887d3acf1b5f81c34
Шаблон:Карточка/Викитека
10
50
98
97
2025-01-25T21:00:23Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#ifeq:{{{1|}}}|нельзя<!--
-->|© Произведения этого автора [[Свободный контент|несвободны]]<!--
-->|{{#if:{{#invoke:Wikidata/Interproject|getWikisourceLink|p103}}<!--
-->|[[Файл:wikisource-logo.svg|15px|Логотип Викитеки|link={{#invoke:Wikidata/Interproject|getWikisourceLink|p103}}]] [[{{#invoke:Wikidata/Interproject|getWikisourceLink|p103}}|{{#if:{{{2|}}}|{{удалить теги|{{delink|{{{2}}}}}}}|{{Сначала имя|{{PAGENAME}}}}}} в Викитеке]]<!--
-->|{{#if:{{{1|}}}|[[Файл:wikisource-logo.svg|15px|Логотип Викитеки|link=[[:s:{{{1|}}}]]]] [[:s:{{{1|}}}|{{#if:{{{2|}}}|{{удалить теги|{{delink|{{{2}}}}}}}|{{Сначала имя|{{PAGENAME}}}}}} в Викитеке]]}}<!--
-->}}<!--
-->{{#if:{{{nocat|}}}{{NAMESPACE}}||{{#if:{{{1|}}}|[[Категория:Википедия:Ссылка на Викитеку непосредственно в статье]]}}}}<!--
-->}}<noinclude>
{{doc}}
</noinclude>
aac8463be78041fae4a55bf222430b207987f063
Шаблон:Сначала имя
10
51
100
99
2025-01-25T21:00:24Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{safesubst:<noinclude />#ifexpr: {{safesubst:<noinclude />str find|{{safesubst:<noinclude />До символа|{{{1}}}|(}}|,}} = -1 <!--
-->|{{safesubst:<noinclude />До символа|{{{1}}}|(}}<!--
-->|{{safesubst:<noinclude />trim|{{safesubst:<noinclude />После символа|{{safesubst:<noinclude />До символа|{{{1}}}|(}}|,}}}} {{safesubst:<noinclude />До символа|{{safesubst:<noinclude />До символа|{{{1}}}|(}}|,}}<!--
-->}}<noinclude>
{{doc}}
</noinclude>
c3a2e3e13dba0ae595a7c147ca692be2eb183f38
Шаблон:Str find
10
52
102
101
2025-01-25T21:00:24Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{ {{{|safesubst:}}}#invoke:String|str_find|source={{{1|}}}|{{{2|}}}}}<noinclude>
{{doc}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
18d1469d30d27a82ee15fd2fb1ca12a34b5f5e87
Шаблон:До символа
10
53
104
103
2025-01-25T21:00:24Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{ {{{|safesubst:}}}#invoke:string2|bs|{{{1|}}}|{{{2|}}}|{{{from|1}}}}}<noinclude>{{doc}}</noinclude>
4cd51dc75d5f365cffac57c9577bd2b2f5c7cc3f
Модуль:Wikidata/media
828
54
106
105
2025-01-25T21:00:24Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local p = {}
-- Константы
local contentLanguageCode = mw.getContentLanguage():getCode();
function p.formatCommonsCategory( context, options, value )
local link = 'commons:Category:' .. value
local title = value .. ' на Викискладе'
if ( options['text'] and options['text'] ~= '' ) then
title = options['text']
end
commons = '[[' .. link .. '|' .. title .. ']]'
--Commons icon
if ( not options['icon'] or options['icon'] ~= '-' ) then
local icon_size = '15px'
if ( options['icon_size'] and options['icon_size'] ~= '' ) then
icon_size = options['icon_size']
end
commons = '[[File:Commons-logo.svg|' .. icon_size .. '|link=' .. link .. '|alt=Логотип Викисклада]] ' .. commons
end
--Text before and after link
if ( options['text_before'] and options['text_before'] ~= '' ) then
if ( options['text_before'] ~= '-' ) then
commons = options['text_before'] .. ' ' .. commons
end
end
if ( options['text_after'] and options['text_after'] ~= '' ) then
if ( options['text_after'] ~= '-' ) then
commons = commons .. ' ' .. options['text_after']
end
end
return commons
end
--[[
Временный хак, нужно добавить config, getConfig и getCategoryByCode
в options, чтобы они были доступны в любом месте кода.
]]
local config;
local function getCategoryByCode( code, sortkey )
if config == nil then
config = require( 'Module:Wikidata/config' );
end;
local value = config[ 'categories' ][ code ];
if not value or value == '' then
return '';
end
return '[[Category:' .. value .. ']]';
end
local function getCaption( context, options )
local caption = ''
if options.qualifiers and options.qualifiers.P2096 then
for i, qualifier in pairs( options.qualifiers.P2096 ) do
if ( qualifier
and qualifier.datavalue
and qualifier.datavalue.type == 'monolingualtext'
and qualifier.datavalue.value
and qualifier.datavalue.value.language == contentLanguageCode ) then
caption = qualifier.datavalue.value.text
break
end
end
end
if options['appendTimestamp'] and options.qualifiers and options.qualifiers.P585 and options.qualifiers.P585[1] then
local moment = context.formatValueDefault( context, options, options.qualifiers.P585[1].datavalue )
if not caption or caption == '' then
caption = moment
else
caption = caption .. ', ' .. moment
end
end
local localValue = '';
if options[ 'value' ] and options[ 'value' ] ~= '' then
localValue = options[ 'value' ];
end
local localCaption = '';
if options[ 'caption' ] and options[ 'caption' ] ~= '' then
localCaption = options[ 'caption' ];
end
if localValue ~= '' then
caption = localCaption;
end
local formattedCaption = ''
if caption ~= '' then
formattedCaption = context.wrapQualifier( caption, 'P2096', { class = 'media-caption', style = 'display:block' } );
end
if localValue == '' and localCaption ~= '' then
formattedCaption = formattedCaption .. getCategoryByCode( 'media-contains-local-caption' )
if options.frame:preprocess('{{REVISIONID}}') == '' then
formattedCaption = formattedCaption .. '<span class="error" style="font-size:94%;">Локальная подпись не используется, потому что изображение берётся из Викиданных, см. [[Википедия:Шаблоны-карточки#Описание изображения в Викиданных|здесь]]</span>'
end
end
return caption, formattedCaption
end
function p.formatCommonsMediaValue( context, options, value )
local image = value;
local caption, formattedCaption = getCaption( context, options )
if not string.find( value, '[%[%]%{%}]' ) and not string.find( value, 'UNIQ%-%-imagemap' ) then
-- если в value не содержится викикод или imagemap, то викифицируем имя файла
-- ищем слово imagemap в строке, потому что вставляется плейсхолдер: [[PHAB:T28213]]
image = '[[File:' .. value .. '|frameless';
if options[ 'border' ] and options[ 'border' ] ~= '' then
image = image .. '|border';
end
local size = options[ 'size' ];
if size and size ~= '' then
if not string.match( size, 'px$' )
and not string.match( size, 'пкс$' ) -- TODO: использовать перевод для языка вики
then
size = size .. 'px'
end
-- временно
if string.match( size, 'pxpx' ) then
image = '[[Категория:Википедия:Изображение с pxpx в размере]]' .. image
end
else
size = fileDefaultSize;
end
image = image .. '|' .. size;
if options[ 'alt' ] and options[ 'alt' ] ~= '' then
image = image .. '|alt=' .. options[ 'alt' ];
end
if caption ~= '' then
image = image .. '|' .. caption
end
image = image .. ']]';
if formattedCaption ~= '' then
image = image .. '<br>' .. formattedCaption;
end
else
image = image .. formattedCaption .. getCategoryByCode( 'media-contains-markup' );
end
if options.entity and options.fixdouble then
local page = mw.title.getCurrentTitle()
local txt = page:getContent()
if txt and txt:match(':' .. value) and mw.title.getCurrentTitle():inNamespace(0) then
if options.frame:preprocess('{{REVISIONID}}') == '' then
image = image .. '<span class="error">Это изображение встречается ниже по тексту статьи; пожалуйста, уберите одну из копий (не потеряв при этом подпись)</span>'
end
image = image .. getCategoryByCode( 'media-contains-local-double' )
end
end
return image
end
return p
ec384e72491465f4103cce95a8f9467df428a432
Модуль:Infocards
828
55
108
107
2025-01-25T21:00:25Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local infocards = {}
local calculateAge = true
local dateCat = require( 'Module:Infocards/dateCat' )
local moduleDates = require( 'Module:Dates' )
--[[
Helper function that populates the argument list given that user may need to use a mix of
named and unnamed parameters. This is relevant because named parameters are not
identical to unnamed parameters due to string trimming, and when dealing with strings
we sometimes want to either preserve or remove that whitespace depending on the application.
]]
function infocards._getParameters( frame_args, arg_list )
local new_args = {}
local index = 1
local value
for i,arg in ipairs( arg_list ) do
value = frame_args[arg]
if value == nil then
value = frame_args[index]
index = index + 1
end
new_args[arg] = value
end
return new_args
end
function infocards.isBlank( someString )
return someString == nil or mw.ustring.match(someString, '^%s*$') ~= nil
end
function infocards.isDate ( frame )
local new_args = infocards._getParameters( frame.args, {'s', 't', 'f'} )
local s = new_args['s'] or ''
local t = new_args['t'] or ''
local f = new_args['f'] or ''
local result = infocards.isDateImpl ( s )
if (result) then
return t
else
return f
end
end
function infocards.isDateImpl ( s )
local converted = infocards.convertToDate ( s )
return converted ~= nil
end
function infocards.dateOfBirth( frame )
local new_args = infocards._getParameters( frame.args, {'dateOfBirth', 'dateOfDeath', 'suppressAge', 'nocat'} )
local dateOfBirth = new_args['dateOfBirth'] or ''
local dateOfDeath = new_args['dateOfDeath'] or ''
local suppressAge = new_args['suppressAge'] or ''
local nocat = new_args['nocat'] or mw.title.getCurrentTitle().nsText
return infocards.dateOfBirthImpl( dateOfBirth, dateOfDeath, suppressAge, nocat )
end
function infocards.dateOfBirthImpl( dateOfBirth, dateOfDeath, suppressAge, nocat )
local appendToCategory = infocards.isBlank( nocat )
if ( infocards.isBlank( dateOfBirth ) ) then
if ( appendToCategory ) then
return dateCat.categoryNoBirthDate
else
return ''
end
end
if ( mw.ustring.match( dateOfBirth, '^%s*неизвестн.%s*$' ) ~= nil
or mw.ustring.match( dateOfBirth, '^%s*%?%s*$' ) ~= nil ) then
if ( appendToCategory ) then
return "''неизвестно''" .. dateCat.categoryUnknownBirthDate
else
return "''неизвестно''"
end
end
local appendAge = not (suppressAge ~= '' or not calculateAge) and infocards.isBlank( dateOfDeath )
local parsedDate = infocards.convertToDate ( dateOfBirth )
if ( parsedDate == nil ) then
--[[ Temporary hack in order to enable export dates to wikidata ]]
local bDateStart = '<span class="no-wikidata" data-wikidata-property-id="P569">'
local bDateEnd = '</span>'
if ( appendToCategory ) then
return bDateStart .. dateOfBirth .. bDateEnd .. dateCat.categoryManualWikification
else
return bDateStart .. dateOfBirth .. bDateEnd
end
end
local result = infocards.formatDateImpl ( parsedDate, 'bday', appendToCategory and 'Родившиеся' or nil )
if ( appendAge ) then
-- TODO: месяцы и дни для (нескольких) новорождённых (см. новейшие [[Категория:Родившиеся в ГГГГ году]])
local age = infocards.age ( parsedDate, os.date("*t") )
if ( age and age < 125) then
result = result .. ' <span class="nowrap">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>'
end
if ( appendToCategory ) then
if (not age and parsedDate and parsedDate.year ) then
age = os.date('*t').year - parsedDate.year -- при неточной дате
end
if ( age ) then
if ( age > 115 ) then
result = result .. dateCat.categoryBigCurrentAge
elseif ( age >= 0 ) then
result = result .. dateCat.categoryBiographiesOfLivingPersons
else
result = result .. dateCat.categoryNegativeAge
end
end
end
end
return result
end
function infocards.dateOfDeath( frame )
local new_args = infocards._getParameters( frame.args, {'dateOfBirth', 'dateOfDeath', 'nocat'} )
local dateOfBirth = new_args['dateOfBirth'] or ''
local dateOfDeath = new_args['dateOfDeath'] or ''
local nocat = new_args['nocat'] or mw.title.getCurrentTitle().nsText
return infocards.dateOfDeathImpl( dateOfBirth, dateOfDeath, nocat )
end
function infocards.dateOfDeathImpl( dateOfBirth, dateOfDeath, nocat )
if ( infocards.isBlank( dateOfDeath ) ) then
return ''
end
local appendToCategory = infocards.isBlank( nocat )
if ( mw.ustring.match( dateOfDeath, '^%s*неизвестн.%s*$' ) ~= nil
or mw.ustring.match( dateOfDeath, '^%s*%?%s*$' ) ~= nil ) then
if ( appendToCategory ) then
return "''неизвестно''" .. dateCat.categoryUnknownDeathDate
else
return "''неизвестно''"
end
end
local parsedDateOfBirth = infocards.convertToDate ( dateOfBirth )
local parsedDateOfDeath = infocards.convertToDate ( dateOfDeath )
if ( parsedDateOfDeath == nil ) then
--[[ Temporary hack in order to enable export dates to wikidata ]]
local dDateStart = '<span class="no-wikidata" data-wikidata-property-id="P570">'
local dDateEnd = '</span>'
if ( appendToCategory ) then
return dDateStart .. dateOfDeath .. dDateEnd .. dateCat.categoryManualWikification
else
return dDateStart .. dateOfDeath .. dDateEnd
end
end
local result = infocards.formatDateImpl ( parsedDateOfDeath, 'dday', appendToCategory and 'Умершие' or nil )
if ( calculateAge ) then
local age = infocards.age ( parsedDateOfBirth, parsedDateOfDeath )
if ( age and age > 0 ) then
result = result .. ' <span class="nowrap">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>'
end
-- returns category to recently deceased persons
local unixAvailable, unixDateOfDeath = pcall(function()
local r = os.time(parsedDateOfDeath)
if ( r ~= os.time() ) then
return r
end
error()
end)
if (appendToCategory) then
if ( unixAvailable and os.time() - unixDateOfDeath < 31536000 ) then
result = result .. dateCat.categoryRecentlyDeceased
elseif (age and age < 0) then
result = result .. dateCat.categoryNegativeAge
end
end
end
return result
end
function infocards.age( parsedBirthDate, parsedFinishDate )
if ( parsedBirthDate == nil or parsedFinishDate == nil ) then
return nil
end
local bd = parsedBirthDate["day"]
local bm = parsedBirthDate["month"]
local by = parsedBirthDate["year"]
local dd = parsedFinishDate["day"]
local dm = parsedFinishDate["month"]
local dy = parsedFinishDate["year"]
if ( bd and bm and by and dd and dm and dy ) then
if ( dm > bm or ( dm == bm and dd >= bd ) ) then
return dy - by
else
return dy - by - 1
end
else
return nil
end
end
function infocards.formatDateImpl( parsedDate, infocardClass, categoryNamePrefix )
local datePart = '<span class="nowrap">'
--Temporary hack in order to enable export dates to wikidata
if infocardClass == "bday" then
datePart = '<span class="no-wikidata" data-wikidata-property-id="P569">'
elseif infocardClass == "dday" then
datePart = '<span class="no-wikidata" data-wikidata-property-id="P570">'
end
local t1 = { day = parsedDate.osday, month = parsedDate.osmonth, year = parsedDate.osyear }
local t2 = { day = parsedDate.day, month = parsedDate.month, year = parsedDate.year }
datePart = datePart .. moduleDates.formatWikiImpl( t1, t2, infocardClass, categoryNamePrefix )
datePart = datePart .. '</span>'
return datePart
end
function infocards.convertToDate( possibleDateString )
possibleDateString = mw.ustring.gsub( possibleDateString, '−', '-')
local simpleDate = mw.ustring.match(possibleDateString, '^%s*([%-%d%.]+)%s*$', 0)
if ( simpleDate ) then
return infocards.convertToDateNewStylePart( simpleDate )
end
local complexDate1, complexDate2 = mw.ustring.match(possibleDateString, '^%s*([%-%d%.]+)%s*%(([%-%d%.]+)%)%s*$', 0)
if ( complexDate1 and complexDate2) then
local table1 = infocards.convertToDateNewStylePart( complexDate1 )
local table2 = infocards.convertToDateOldStylePart( complexDate2 )
if ( table1 and table2 ) then
return {
year = table1["year"], month = table1["month"], day = table1["day"],
osyear = table2["year"], osmonth = table2["month"], osday = table2["day"]
}
else
return nil
end
end
return nil
end
function infocards.convertToDateNewStylePart( possibleDateString )
local ny = mw.ustring.match(possibleDateString, '^(%-?%d+)$', 0)
if (ny ~= nil) then
return {year = tonumber(ny)}
end
return infocards.convertToDateCommonPart( possibleDateString )
end
function infocards.convertToDateOldStylePart( possibleDateString )
local nd = mw.ustring.match(possibleDateString, '^(%-?%d+)$', 0)
if (nd ~= nil) then
return {day = tonumber(nd)}
end
return infocards.convertToDateCommonPart( possibleDateString )
end
function infocards.convertToDateCommonPart( possibleDateString )
local sDay, sMonth, sYear
local day, month, year
sDay, sMonth, sYear = mw.ustring.match( possibleDateString, '^(%d?%d)%.(%d?%d)%.(%-?%d+)$', 0 )
if sDay ~= nil and sMonth ~= nil and sYear ~= nil then
day = tonumber( sDay )
month = tonumber( sMonth )
year = tonumber( sYear )
if day >= 1 and day <= 32 and month >= 1 and month <= 12 then
return { day = day, month = month, year = year }
end
end
sDay, sMonth = mw.ustring.match( possibleDateString, '^(%d?%d)%.(%d?%d+)$', 0 )
if sDay ~= nil and sMonth ~= nil then
day = tonumber( sDay )
month = tonumber( sMonth )
if day >= 1 and day <= 32 and month >= 1 and month <= 12 then
return { day = day, month = month }
end
end
sMonth, sYear = mw.ustring.match( possibleDateString, '^(%d?%d)%.(%-?%d+)$', 0 )
if sMonth ~= nil and sYear ~= nil then
month = tonumber( sMonth )
year = tonumber( sYear )
if month >= 1 and month <= 12 then
return { month = month, year = year }
end
end
return nil
end
return infocards
6c1e746d6605d4d101f6aa9fd3e4824b60c64ef7
Модуль:Infocards/dateCat
828
56
110
109
2025-01-25T21:00:25Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local p = {}
p.categoryUnknownBirthDate = '[[Категория:Персоналии, чья дата рождения не установлена]]'
p.categoryUnknownDeathDate = '[[Категория:Персоналии, чья дата смерти не установлена]]'
p.categoryBigCurrentAge = '[[Категория:Персоналии с большим текущим возрастом]]' --бывш. [[Категория:Википедия:Статьи о персоналиях с большим текущим возрастом]]
p.categoryNegativeAge = '[[Категория:Персоналии с отрицательным возрастом]]'
-- p.categoryBigDeathAge = '[[Категория:Википедия:Статьи о персоналиях с большим возрастом во время смерти]]' //deleted -d.bratchuk 05-07-2016
p.categoryBiographiesOfLivingPersons = '[[Категория:Википедия:Биографии современников]]'
p.categoryRecentlyDeceased = '[[Категория:Персоналии, умершие менее года назад]]'
p.categoryManualWikification = '[[Категория:Википедия:Статьи с ручной викификацией дат в карточке]]'
p.categoryNoBirthDate = '[[Категория:Персоналии без указанной даты рождения]]' --бывш. [[Категория:Википедия:Персоны без указанной даты рождения]]
return p
6b27e44bc0a4aaafa42074ca16db92b13e4999d4
Модуль:Wikidata/Interproject
828
57
112
111
2025-01-25T21:00:26Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local p = {}
function p.getWikivoyageLink( context )
return p.getSisterProjectLink( 'voy', 'wikivoyage', context )
end
function p.getWikibooksLink( context )
return p.getSisterProjectLink( 'b', 'wikibooks', context )
end
function p.getWikiquoteLink( context )
return p.getSisterProjectLink( 'q', 'wikiquote', context )
end
function p.getWikisourceLink( context )
return p.getSisterProjectLink( 's', 'wikisource', context )
end
function p.getWikipediaLink( context )
return p.getSisterProjectLink( 'w', 'wiki', context )
end
function p.getWiktionaryLink( context )
return p.getSisterProjectLink( 'wikt', 'wiktionary', context )
end
function p.getSisterProjectLink( projectInterwikiPrefix, projectName, context )
-- проброс параметра from откуда угодно
local entityId = nil
local p_context = context
while p_context do
if p_context.args and p_context.args.from and p_context.args.from ~= '' then
if p_context.args.from == '-' then
return ''
end
entityId = p_context.args.from
else
entityId = mw.wikibase.getEntityIdForCurrentPage()
end
p_context = p_context:getParent()
end
-- По умолчанию старается достать ссылку на русском, иначе - на родном (P103)
local wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId, 'ru' .. projectName )
if wbStatus and sitelink then
return projectInterwikiPrefix .. ':' .. sitelink
end
local wbStatus, langClaims = pcall( mw.wikibase.getBestStatements, entityId, 'P103' )
if wbStatus ~= true or not langClaims then
return ''
end
local codes = mw.loadData( 'Module:Wikidata:Dictionary/P424' )
for _, claim in ipairs( langClaims ) do
if claim.mainsnak and
claim.mainsnak.datavalue and
claim.mainsnak.datavalue.value and
claim.mainsnak.datavalue.value.id
then
local codesById = codes[ claim.mainsnak.datavalue.value.id ]
if codesById then
for _, code in ipairs( codesById ) do
wbStatus, sitelink = pcall( mw.wikibase.getSitelink, entityId, code .. projectName )
if wbStatus and sitelink then
return projectInterwikiPrefix .. ':' .. code .. ':' .. sitelink
end
end
end
end
end
return ''
end
return p
48f3bdd682abd29718705f19e0411be2db6490cd
Модуль:String2
828
58
114
113
2025-01-25T21:00:26Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--[[
Кое-какие дополнительные функции для строк
]]
local M = {
bs=function(f)-- первый параметр до начала второго параметра (или до конца, если он не встретился)
--необяз. 3-й параметр - с какого по номеру (с 1) символа начинать поиск.
return mw.ustring.sub(f.args[1], 1, (mw.ustring.find(f.args[1],f.args[2],tonumber(f.args[3] or 1),true) or 0)-1)
end;
as=function(f)-- первый параметр после начала второго параметра
return mw.ustring.sub(f.args[1], (mw.ustring.find(f.args[1],f.args[2],1,true) or 0)+1)
end;
Tr=function(s,f,t,cf,df,sf)-- транслитерация первого параметра путём замены символов из второго параметра символами из третьего.
-- Отдельными параметрами можно передавать флаги c, d и s, как в Perl; диапазоны в замене не работают, только в левой части
-- (т.е. дефис надо передавать первым или последним). Второй результат - число заменённых символов
local r, l, l2 = {}, mw.ustring.len(f), mw.ustring.len(t);
for i = 1, l do
r[mw.ustring.sub(f,i,i)] = i<=l2 and mw.ustring.sub(t,i,i) or df and '' or mw.ustring.sub(t,l2,l2)
end
local n2=0;
local res, n = mw.ustring.gsub(
s,
('[%s%s]%s'):format(
cf and '^' or '',
f:gsub('%','%%'):gsub(']','%]'):gsub('^%^','%^'),
sf and '+' or ''
),
sf and function(cc)
n2 = n2+mw.ustring.len(cc)-1;
return mw.ustring.gsub(cc,'.',r)
end or r
)
return res, n+n2
end;
-- tr = function(f) return (M.Tr(f.args[1],f.args[2],f.args[3],f.args['c'],f.args['d'],f.args['s'])) end;-- транслитерировать
-- trс = function(f) return ({M.Tr(f.args[1],f.args[2],f.args[3],f.args['c'],f.args['d'],f.args['s'])})[2] end;-- посчитать символы
Trg = function(s,t,f,fi)-- Производит замену строк произвольной длины (если с fi, регистр не учитывает).
-- Приоритет - по порядку в таблицах.
for n,p in ipairs(t) do
t[n] = {fi and mw.ustring.upper(p) or p,mw.ustring.len(p)}
end
local r,i,l,N = {},1,mw.ustring.len(s),0
while i<=l do
(function()
for n,p in ipairs(t) do
if ( fi and mw.ustring.upper(mw.ustring.sub(s,i,i+p[2]-1)) or mw.ustring.sub(s,i,i+p[2]-1) ) == p[1] then
table.insert(r,f[n]);
i = i+p[2]; N=N+1;
return
end
end
table.insert(r,mw.ustring.sub(s,i,i));
i=i+1;
return
end)()
end
return table.concat(r),N
end;
trg = function(frame)--Работает с номерными аргументами шаблона,если задан параметр u, иначе со своими.
-- Заменяет в первом аргументе аргументы 2, 4, 6... на аргументы 3, 5, 7...
local tf, t, f, i= frame.args['u'] and frame.getParent() or f, {}, {}, 1;
while tf.args[2*i] do t[tf.args[2*i]]=tf.args[2*i+1] or '' end
return ( M.Trg(tf.args[1],t,f,(frame.args['i'] or '')~='') )
end;
join = function (f) --объединяет нумерованные аргументы вызвавшего шаблона
-- от from или 1 до to или первого отсутствующего
-- через первый параметр invoke. Последний элемент можно присоединять иначе, задав второй параметр.
-- По умолчанию ',' & 'и'
-- Если 3-й параметр invoke — "s", строки из пробелов игнорируются; если "_", игнорируются пустые строки
local t, tf, i = {}, f:getParent(), tonumber(f.args.from) or 1
local k,j,m = tonumber(f.args.to),i,f.args[3]
while k and i<=k or tf.args[i] do
if (
({
['_']=function(s)return s~=''end;
['s']=function(s)return not tostring(s):match("^%s*$")end
})[m] or function() return true end
)(tf.args[i]) then
t[j]=tf.args[i];
j=j+1
end;
i=i+1
end
return mw.text.listToText(t,f.args[1],f.args[2] or f.args[1])
end
}
function M.formatRound(frame) --форматирует число, чтобы оно имело order знаков после запятой
return string.format("%0."..frame.args[2].."f",tonumber(frame.args[1]));
end
-- если строка s содержит число, увеличивает первое такое число на n, иначе возращает пустую строку.
-- если число начинается на 0, то увеличенное число будет содержать по крайне мере столько цифр сколько исходное.
function M.increase(s, n)
local a,b,c = string.match(s, "([^0-9]*)([0-9]+)(.*)")
if b==nil then return s end
local num = tonumber(b) + n
if b:sub(1,1)=='0'
then b = string.format("%0"..b:len().."d", num)
else b=num
end
return a .. b .. c
end
function M.ucfirst(frame )
local s = mw.text.trim( frame.args[1] or "" )
local s1 = ""
-- if it's a list chop off and (store as s1) everything up to the first <li>
local lipos = string.find(s, "<li>" )
if lipos then
s1 = string.sub(s, 1, lipos + 3)
s = string.sub(s, lipos + 4)
end
-- s1 is either "" or the first part of the list markup, so we can continue
-- and prepend s1 to the returned string
local letterpos
if string.find(s, "^%[%[[^|]+|[^%]]+%]%]") then
-- this is a piped wikilink, so we capitalise the text, not the pipe
local _
_, letterpos = string.find(s, "|%A*%a") -- find the first letter after the pipe
else
letterpos = string.find(s, '%a')
end
if letterpos then
local first = string.sub(s, 1, letterpos - 1)
local letter = string.sub(s, letterpos, letterpos)
local rest = string.sub(s, letterpos + 1)
return s1 .. first .. string.upper(letter) .. rest
else
return s1 .. s
end
end
return M
1d51eb45a573b689485dad672c0968c18ec3b342
Модуль:Wikidata/date
828
59
116
115
2025-01-25T21:00:27Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--settings
local nowLabel = 'наст. время'
local moduleDates = require( "Module:Dates" )
local moduleWikidata = require( "Module:Wikidata" )
local dateCat = require("Module:Infocards/dateCat")
-- FIXME: undeclared global variable, used 3 times
local infoclass
local function deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
setmetatable(copy, deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
local function ageImpl ( bStructure, bPrecision, dStructure, dPrecision )
if ( not bStructure or not dStructure or bPrecision < 10 or dPrecision < 10 ) then
return nil
end
local shift = 0
if ( bStructure.year < 0 and dStructure.year > 0 ) then
shift = -1
end
if ( bPrecision == 10 or dPrecision == 10 ) then
if ( bStructure.month < dStructure.month ) then
return dStructure.year - bStructure.year + shift
end
if ( bStructure.month == dStructure.month ) then
return nil
end
if ( bStructure.month > dStructure.month ) then
return dStructure.year - bStructure.year - 1 + shift
end
end
if ( bStructure.month < dStructure.month ) then
return dStructure.year - bStructure.year + shift
end
if ( bStructure.month == dStructure.month ) then
if ( bStructure.day <= dStructure.day ) then
return dStructure.year - bStructure.year + shift
else
return dStructure.year - bStructure.year - 1 + shift
end
end
if ( bStructure.month > dStructure.month ) then
return dStructure.year - bStructure.year - 1 + shift
end
return nil
end
-- accepts table of time+precision values
local function ageCurrent ( bTable )
local possibleAge = "NYA" -- it means "Not Yet Assigned", not what you imagined!
for bKey, bValue in pairs(bTable) do
if ( bValue.unknown ) then
return nil
end
local bStructure = bValue.structure
local bPrecision = bValue.precision
local dStructure = os.date( "*t" )
local calculatedAge = ageImpl ( bStructure, bPrecision, dStructure, 11 )
if ( possibleAge == "NYA" ) then
possibleAge = calculatedAge
else
if ( possibleAge ~= calculatedAge ) then
possibleAge = nil
end
end
end
return possibleAge
end
-- accepts tables of time+precision values
local function age ( bTable, dTable )
local possibleAge = "NYA" -- it means "Not Yet Assigned", not what you imagined!
for bKey, bValue in pairs( bTable ) do
if ( bValue.unknown ) then
return nil
end
local bStructure = bValue.structure
local bPrecision = bValue.precision
for dKey, dValue in pairs( dTable ) do
if ( dValue.unknown ) then
return nil
end
local dStructure = dValue.structure
local dPrecision = dValue.precision
if ( bValue.calendar == 'julian' and dValue.calendar == 'gregorian' ) then
-- to calculate age, need to adjust bStructure to gregorian calendar
local shift = math.floor(bStructure.year/100-2) - math.floor(bStructure.year/400)
-- TODO: re-implement this properly
bStructure.day = bStructure.day + shift
end
local calculatedAge = ageImpl ( bStructure, bPrecision, dStructure, dPrecision )
if ( possibleAge == "NYA" ) then
possibleAge = calculatedAge
else
if ( possibleAge ~= calculatedAge ) then
possibleAge = nil
end
end
end
end
return possibleAge
end
local function parseISO8601Date(str)
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local Y, M, D = mw.ustring.match( str, pattern )
return tonumber(Y), tonumber(M), tonumber(D)
end
local function parseISO8601Time(str)
local pattern = "T(%d+):(%d+):(%d+)%Z"
local H, M, S = mw.ustring.match( str, pattern)
return tonumber(H), tonumber(M), tonumber(S)
end
local function parseISO8601Offset(str)
if str:sub(-1)=="Z" then return 0,0 end -- ends with Z, Zulu time
-- matches ±hh:mm, ±hhmm or ±hh; else returns nils
local pattern = "([-+])(%d%d):?(%d?%d?)$"
local sign, oh, om = mw.ustring.match( str, pattern)
sign, oh, om = sign or "+", oh or "00", om or "00"
return tonumber(sign .. oh), tonumber(sign .. om)
end
local function parseISO8601(str)
if 'table' == type(str) then
if str.args and str.args[1] then
str = '' .. str.args[1]
else
return 'unknown argument type: ' .. type( str ) .. ': ' .. table.tostring( str )
end
end
local Y,M,D = parseISO8601Date(str)
local h,m,s = parseISO8601Time(str)
local oh,om = parseISO8601Offset(str)
if not Y or not M or not D or not h or not m or not s or not oh or not om then
return nil
end
return tonumber(os.time({year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s}))
end
local function parseClaim ( claim )
if ( claim.mainsnak.snaktype == "value" ) then
local timeISO8601 = string.gsub( string.gsub( tostring( claim.mainsnak.datavalue.value.time ), '-00%-', '-01-' ), '-00T', '-01T' )
local unixtime = parseISO8601( timeISO8601 )
local structure = os.date("*t", unixtime)
local precision = tonumber( claim.mainsnak.datavalue.value.precision )
local calendarmodel = 'gregorian'
if (mw.ustring.find(claim.mainsnak.datavalue.value.calendarmodel, 'Q1985786', 1, true)) then
calendarmodel = 'julian'
end
local item = { structure=structure, precision=precision, calendar = calendarmodel }
return item
elseif ( claim.mainsnak.snaktype == "novalue" ) then
-- novalue
return { unknown="novalue" }
else
--unknown
return { unknown="unknown" }
end
end
-- returns table of time+precision values for specified property
local function parseProperty ( context, options, propertyId )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not options.entity ) then error( 'options.entity is missing'); end
if ( not propertyId ) then error( 'propertyId not specified'); end
local claims = context.selectClaims( options, propertyId )
if not claims then
return nil
end
local result = {}
for key, claim in pairs( claims ) do
table.insert ( result, parseClaim( claim ) )
end
return result
end
-- проверка на совпадающие даты с разной моделью календаря
local function checkDupDates( t )
if #t > 1 then
local removed = false
local j = 1
-- проверка на совпадающие даты с разной моделью календаря
while (j <= #t) do
local i = 1
while (i <= #t) do
if i ~= j then
if (os.time(t[j].structure) == os.time(t[i].structure)) then
if ((t[j].calendarmodel == 'gregorian') and
(t[i].calendarmodel == 'julian')) then
removed = true
break
else
table.remove(t, i)
end
else
i = i + 1
end
else
i = i + 1
end
end
if removed then
removed = false
table.remove(t, j)
else
j = j+1
end
end
end
end
-- returns first qualifier of specified propertyId
local function getQualifierWithDataValue( statement, qualifierPropertyId )
if ( statement.qualifiers
and statement.qualifiers[qualifierPropertyId] ) then
local qualifiers = statement.qualifiers[qualifierPropertyId]
for _, qualifier in ipairs( qualifiers ) do
if (qualifier.datavalue) then
return qualifier
end
end
end
return nil
end
local p = {}
local function formatDecade( time, categoryNamePrefix )
local bce = ''
local year
if time.year < 0 then
bce = ' до н. э.'
year = math.floor( math.abs( time.year ) / 10 ) * 10
else
year = math.floor( time.year / 10 ) * 10
end
local unit = '-е'
if isGenitive then
unit = '-х'
end
local value = '' .. year .. unit .. bce
if categoryNamePrefix then
return value .. '[[Category:' .. categoryNamePrefix .. ' в ' .. year .. '-е годы' .. bce .. ']]'
end
return value
end
local function formatCentury( time, categoryNamePrefix, isGenitive )
local moduleRoman = require( 'Module:RomanNumber' )
local bce = ''
local century
if time.year < 0 then
bce = ' до н. э.'
century = math.floor( ( math.abs( time.year ) - 1 ) / 100 ) + 1
else
century = math.floor( ( time.year - 1 ) / 100 ) + 1
end
local unit = 'век'
if isGenitive then
unit = 'века'
end
local infix = ' в '
if century == 2 then
infix = ' во '
end
if moduleRoman then
century = moduleRoman.toRomanNumber( century )
end
local value = '[[' .. century .. ' век' .. bce .. '|' .. century .. ' ' .. unit .. bce .. ']]'
if categoryNamePrefix then
return value .. '[[Category:' .. categoryNamePrefix .. infix .. century .. ' веке' .. bce .. ']]'
end
return value
end
local function formatMillenium( time, categoryNamePrefix, isGenitive )
local bce = ''
local millenium
if time.year < 0 then
bce = ' до н. э.'
millenium = math.floor( ( math.abs( time.year ) - 1 ) / 1000 ) + 1
else
millenium = math.floor( ( time.year - 1 ) / 1000 ) + 1
end
local unit = '-е тысячелетие'
if isGenitive then
unit = '-го тысячелетия'
end
local value = '[[' .. millenium .. '-е тысячелетие' .. bce .. '|' .. millenium .. unit .. bce .. ']]'
if categoryNamePrefix then
local infix = ' в '
if millenium == 2 then
infix = ' во '
end
return value .. '[[Category:' .. categoryNamePrefix .. infix .. millenium .. '-м тысячелетии' .. bce .. ']]'
else
return value
end
end
local function formatDateImpl( value, options, microformatClass, categoryPrefix, leftBracket, rightBracket, nolinks, isGenitive )
if ( not value ) then error( 'value not specified'); end
if ( not options ) then error( 'options not specified'); end
-- The calendar model used for saving the data is always the proleptic Gregorian calendar according to ISO 8601.
local timeISO8601 = string.gsub( string.gsub( tostring( value.time ), '-00%-', '-01-' ), '-00T', '-01T' )
local unixtime = parseISO8601( timeISO8601 )
if not unixtime then
return ''
end
local structure = os.date("*t", unixtime)
local precision = tonumber( value.precision )
if precision <= 6 then
return formatMillenium( structure, categoryPrefix, isGenitive )
end
if precision == 7 then
return formatCentury( structure, categoryPrefix, isGenitive )
end
if precision == 8 then
return formatDecade( structure, categoryPrefix, isGenitive )
end
if precision == 9 then
local tCopy = deepcopy( structure )
tCopy.day = nil
tCopy.month = nil
return moduleDates.formatWikiImpl( tCopy, tCopy, infoclass, categoryPrefix, leftBracket, rightBracket, nolinks )
end
-- year and month only
if precision == 10 then
local tCopy = deepcopy( structure )
tCopy.day = nil
return moduleDates.formatWikiImpl( tCopy, tCopy, infoclass, categoryPrefix, leftBracket, rightBracket, nolinks )
end
local calendarmodel = 'gregorian'
if (mw.ustring.find(value.calendarmodel, 'Q1985786', 1, true)) then
calendarmodel = 'julian'
end
if (calendarmodel == 'gregorian') then
return moduleDates.formatWikiImpl( structure, structure, microformatClass, categoryPrefix, leftBracket, rightBracket, nolinks )
else
return p.formatAsJulian( timeISO8601, infoclass, categoryPrefix, leftBracket, rightBracket, nolinks )
end
end
local function formatApproximateDateClaim( context, options, statement, unknownDateCategory )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not options.entity ) then error( 'options.entity is missing'); end
if ( not statement ) then error( 'statement not specified'); end
if options.nocat then unknownDateCategory = "" end
local qNotSoonerThan = getQualifierWithDataValue( statement, 'P1319' )
local qNotLaterThan = getQualifierWithDataValue( statement, 'P1326' )
if ( qNotSoonerThan or qNotLaterThan ) then
local results = {}
if ( qNotSoonerThan ) then
local formattedDate = formatDateImpl( qNotSoonerThan.datavalue.value, {}, nil, nil, options.leftBracket, options.rightBracket, options.nolinks, true )
local value = 'не ранее ' .. context.wrapSnak( formattedDate, qNotSoonerThan.hash )
table.insert( results, context.wrapQualifier( value, 'P1319' ) )
end
if ( qNotLaterThan ) then
local formattedDate = formatDateImpl( qNotLaterThan.datavalue.value, {}, nil, nil, options.leftBracket, options.rightBracket, options.nolinks, true )
local value = 'не позднее ' .. context.wrapSnak( formattedDate, qNotLaterThan.hash )
table.insert( results, context.wrapQualifier( value, 'P1326' ) )
end
return mw.text.listToText( results, ' и ' , ' и ' ) .. unknownDateCategory .. context.formatRefs( options, statement )
end
return nil
end
function p.formatDateOfBirthClaim( context, options, statement )
local value = formatApproximateDateClaim( context, options, statement, dateCat.categoryUnknownBirthDate )
if value then
return value
end
options['conjunction'] = ' или '
options['value-module'] = 'Wikidata/date'
options['value-function'] = 'formatBirthDate'
options.i18n.somevalue = '\'\'неизвестно\'\'' .. dateCat.categoryUnknownBirthDate
local circumstances = context.getSourcingCircumstances( statement )
for _, itemId in ipairs( circumstances ) do
if itemId == 'Q5727902' then
options.isGenitive = true
break
end
end
local result = context.formatStatementDefault( context, options, statement )
local bTable = { parseClaim( statement ) }
local dTable = parseProperty ( context, options, 'P570' )
if ( bTable and not dTable ) then
local age = ageCurrent( bTable )
if ( age ) then
if ( options.suppressAge == nil or options.suppressAge == '' ) then
result = result .. ' <span style="white-space:nowrap;">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>'
end
if ( not options.nocat ) then
if ( age > 115 ) then
result = result .. dateCat.categoryBigCurrentAge
elseif (age >= 0) then
result = result .. dateCat.categoryBiographiesOfLivingPersons
else
result = result .. dateCat.categoryNegativeAge
end
end
end
end
return result
end
function p.formatDateOfDeathClaim( context, options, statement )
local value = formatApproximateDateClaim( context, options, statement, dateCat.categoryUnknownDeathDate )
if value then
return value
end
options['conjunction'] = ' или '
options['value-module'] = 'Wikidata/date'
options['value-function'] = 'formatDeathDate'
options.i18n.somevalue = '\'\'неизвестно\'\'' .. dateCat.categoryUnknownDeathDate
local circumstances = context.getSourcingCircumstances( statement )
for _, itemId in ipairs( circumstances ) do
if itemId == 'Q5727902' then
options.isGenitive = true
break
end
end
local result = context.formatStatementDefault( context, options, statement )
local bTable = parseProperty ( context, options, 'P569' )
local dTable = { parseClaim( statement ) }
if ( bTable and dTable ) then
local age = age( bTable, dTable )
if ( age ) then
if ( options.suppressAge == nil or options.suppressAge == '' ) then
result = result .. ' <span style="white-space:nowrap;">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>'
end
if ( not options.nocat and age < 0) then
result = result .. dateCat.categoryNegativeAge
end
end
-- returns category to recently deceased persons
local unixAvailable, unixDateOfDeath = pcall(function()
local r = os.time(dTable[1].structure)
if ( r ~= os.time() ) then
return r
end
error()
end)
if ( unixAvailable and os.time() - unixDateOfDeath < 31536000 and not options.nocat ) then
result = result .. dateCat.categoryRecentlyDeceased
end
end
return result
end
-- Reentry point for Wikidata Snak formatting
function p.formatBirthDate( context, options, value )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not value ) then error( 'value not specified'); end
local microformatClass = nil
if options.microformat ~= '-' then
microformatClass = options.microformat or 'bday'
end
if ( options.nocat ) then
return formatDateImpl( value, options, microformatClass, nil, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
else
return formatDateImpl( value, options, microformatClass, 'Родившиеся', options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
end
end
-- Reentry point for Wikidata Snak formatting
function p.formatDeathDate( context, options, value )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not value ) then error( 'value not specified'); end
local microformatClass = nil
if options.microformat ~= '-' then
microformatClass = options.microformat or 'dday'
end
if ( options.nocat and options.nocat ~= '' ) then
return formatDateImpl( value, options, microformatClass, nil, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
else
return formatDateImpl( value, options, microformatClass, 'Умершие', options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
end
end
-- Reentry point for Wikidata Snak formatting -- default one
function p.formatDate( context, options, value )
if ( not context ) then error( 'context not specified'); end
if ( not options ) then error( 'options not specified'); end
if ( not value ) then error( 'value not specified'); end
local microformatClass = options.microformat or nil
if ( options.nocat and options.nocat ~= '' ) then
return formatDateImpl( value, options, microformatClass, nil, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
else
local categoryPrefix = options.categoryPrefix or nil
return formatDateImpl( value, options, microformatClass, categoryPrefix, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive )
end
end
function p.formatDateIntervalProperty( context, options )
if ( not context ) then error( 'context not specified' ); end
if ( not options ) then error( 'options not specified' ); end
if ( not options.entity ) then error( 'options.entity missing' ); end
-- Получение нужных утверждений
local WDS = require( 'Module:WikidataSelectors' )
local fromProperty = options.property
if options.from and options.from ~= '' then
fromProperty = options.from
end
local fromClaims = WDS.load( options.entityId, fromProperty )
local toClaims = WDS.load( options.entityId, options.to )
if fromClaims == nil and toClaims == nil then
return ''
end
local formattedFromClaims = {}
if fromClaims then
for i, claim in ipairs( fromClaims ) do
local formattedStatement = context.formatStatement( options, claim )
if formattedStatement then
formattedStatement = '<span class="wikidata-claim" data-wikidata-property-id="' .. string.upper( options.property ) .. '" data-wikidata-claim-id="' .. claim.id .. '">' .. formattedStatement .. '</span>'
table.insert( formattedFromClaims, formattedStatement )
end
end
end
local formattedToClaims = {}
local toOptions = deepcopy( options )
toOptions.property = options.to
toOptions.novalue = nowLabel
if toClaims then
for i, claim in ipairs( toClaims ) do
local formattedStatement = context.formatStatement( toOptions, claim )
if formattedStatement then
formattedStatement = '<span class="wikidata-claim" data-wikidata-property-id="' .. string.upper( toOptions.property ) .. '" data-wikidata-claim-id="' .. claim.id .. '">' .. formattedStatement .. '</span>'
table.insert( formattedToClaims, formattedStatement )
end
end
end
local out = ''
local fromOut = mw.text.listToText( formattedFromClaims, options.separator, options.conjunction )
local toOut = mw.text.listToText( formattedToClaims, options.separator, options.conjunction )
if fromOut ~= '' or toOut ~= '' then
if fromOut ~= '' then
out = fromOut
else
out = '?'
end
if toOut ~= '' then
out = out .. ' — ' .. toOut
else
local withinClaims = nil
if options.within then
WDS.load( options.entityId, options.within )
end
if withinClaims == nil then
out = 'с ' .. out
else
out = out .. ' — ' .. nowLabel
end
end
end
if out ~= '' then
if options.before then
out = options.before .. out
end
if options.after then
out = out .. options.after
end
end
return out
end
local lowestBoundary = '1582-10-05T00:00:00Z'
local lastBoundary = '1918-01-31T00:00:00Z'
local boundaries = {
-- from (G) till next will be diff(G = J + diff), at current
{ lowestBoundary, 10 },
{ '1700-02-29T00:00:00Z', 11 },
{ '1800-02-29T00:00:00Z', 12 },
{ '1900-02-29T00:00:00Z', 13 },
{ lastBoundary, '' },
}
-- Передаваемое время обязано быть по Юлианскому календарю (старому стилю)
function p.formatAsJulian( julTimeISO8601, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
if 'table' == type( julTimeISO8601 ) then
if julTimeISO8601.args and julTimeISO8601.args[1] then
julTimeISO8601 = julTimeISO8601.args[1]
else
return 'unknown argument type: ' .. type( julTime ) .. ': ' .. table.tostring( julTime )
end
end
julTimeISO8601 = mw.text.trim( julTimeISO8601 )
julTimeISO8601 = string.gsub( julTimeISO8601, '^+', '' )
local julTime = parseISO8601( julTimeISO8601 )
local t = os.date( "*t", julTime )
if ( julTime < parseISO8601( lowestBoundary ) ) then
-- only julian
if string.find( julTimeISO8601, '-02-29T', 1, true ) then
t = { year = t.year, month = 2, day = 29 }
end
return moduleDates.formatWikiImpl( t, t, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
end
if ( julTimeISO8601 >= lastBoundary ) then
return "''некорректная дата (юлианский календарь не используется после 1918-01-26)''"
end
-- julian and grigorian
for i = 1, #boundaries, 1 do
local b1 = boundaries[i][1]
local b2 = boundaries[i + 1][1]
if ( b1 <= julTimeISO8601 and julTimeISO8601 < b2 ) then
local diff = boundaries[i][2]
if string.sub( julTimeISO8601, 1, 10 ) == string.sub( boundaries[i][1], 1, 10 ) then
t = { year = t.year, month = 2, day = 29 }
diff = diff - 1
end
local gregTime = os.date( "*t", julTime + diff * 24 * 60 * 60 )
return moduleDates.formatWikiImpl( t, gregTime, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
end
end
return "''ошибка в модуле Модуль:Wikidata/date''"
end
return p
12c2c34efd103d2938bd65421aa550e8c6f26da0
Шаблон:Join
10
60
118
117
2025-01-25T21:00:27Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:Separated entries|main|separator={{{separator|}}}}}<noinclude>
{{doc}}
<!-- Категории — на подстраницу /doc, интервики — в Викиданные. -->
</noinclude>
92bb17b5322d3ae0ceab93d4dad3d31810d47eb0
Модуль:Dates
828
61
120
119
2025-01-25T21:00:27Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--[[
В это модуле собраны функции, связанные с работой с датами.
]]
local monthg = {'января', 'февраля', 'марта', 'апреля', 'мая', 'июня',
'июля', 'августа', "сентября", "октября", "ноября", "декабря"}
local monthd = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
local function DecodeDate(d)-- Ч, М, Г, СЧ, СМ, СГ, хвост
--дата: "%-?%d+"=год, "%d+%.%d+"=число месяца, "%d+%.%d+%.%-?%d+"=ЧМГ,
-- потом в скобках м.б. переопределено для старого стиля начиная с числа
local nd=d:match("^[%d.-]*");
local od=d:match("^[%d.-]*%s*%(%s*([%d.-]*)%s*%)");
local tail = d:match("^[%d.-]+%s*%(%s*[%d.-]+%s*%)%s*(%S.*)") or d:match("^[%d.-]+%s*([^%s%d].*)");
if nd:match('^%-?%d+$' ) then
return nil, nil, tonumber(nd), nil, nil, od and tonumber(od:match("%-?%d+$")),tail
else
local j,m,y=nd:match("^(%d+)%.(%d+)%.?(%-?%d*)");
if j then
if od then
local oj, om, oy = od:match("^(%d+)%.?(%d*)%.?(%-?%d*)");
return j and tonumber(j),
m and tonumber(m),
y>'' and tonumber(y) or nil,
oj and tonumber(oj),
om>'' and tonumber(om) or nil,
oy>'' and tonumber(oy) or nil,
tail
end
return j and tonumber(j), m and tonumber(m), y>'' and tonumber(y) or nil, nil, nil, nil, tail
else return nil
end
end
end
local function Diffy(d1,m1,y1,d0,m0,y0)--аналог Персона/Дата/Прошло лет
return y1-y0 - ( y1*y0<=0 and 1 or 0 ) - ( (m1<m0 or m1==m0 and d1<d0) and 1 or 0 )
end
local function Year0(y,t)-- аналог Год0
if y>0 then return table.concat{
'[[', tostring(y), ' год|', t and tostring(y)..' '..t or tostring(y), ']]'
} else return table.concat{
'[[', tostring(-y), ' год до н. э.|',
t and tostring(-y)..' '..t or tostring(-y),
' до н. э.]]'
}
end
end
local function FormDate(j,m,y,oj,om,oy,mo)-- ~ Персона/Дата/Logic 4
if j then
if not m then return "''формат неверен''" end
if y then return
string.format(
'<span class="nowrap">%s<span style="display:none">(<span class="%s">%04i-%02i-%02i</span>)</span></span>',
table.concat(
oj and (
om and (
oy and {-- ДД ММММ ГГГГ ([[ДД ММММ]] [[ГГГГ]])
oj,' ',monthg[om],' ',oy,
'</span> <span class="nowrap">([[',
j, ' ', monthg[m],']] ',Year0(y),')'
} or {-- ДД ММММ ([[ДД ММММ]]) [[ГГГГ]]
oj,' ',monthg[om],' ([[',j,' ',monthg[m],']]) ',Year0(y)
}
) or {-- ДД [[ДД ММММ|(ДД) ММММ]] [[ГГГГ]]
oj,' [[',j,' ',monthg[m],'|','(',j,') ',monthg[m],']] ',Year0(y)
}
) or {'[[',j,' ',monthg[m],']] ',Year0(y)}
),--/table.concat
({['Рождения']='bday',['Смерти']='dday'})[mo] or '',
y,m,j
)--/string.format
else return
'<span class="nowrap">' .. table.concat(
oj and (
om and {-- ДД ММММ ([[ДД ММММ]])
oj,' ',monthg[om],' ([[',j,' ',monthg[m],']])</span>'
} or {-- ДД [[ДД ММММ|(ДД) ММММ]]
oj,' [[',j,' ',monthg[m],'|','(',j,') ',monthg[m],']]</span>'
}
) or {'[[',j,' ',monthg[m],']]</span>'}
)
end
else
return y and string.format(
'<span class="nowrap">%s<span style="display:none;">(<span class="bday">%04i</span>)</span></span>',
Year0(y,'год'),y) or "''формат неверен''"
end
end
local function GetDate(D)--dd.mm.-?yyyy или -?yyyy-mm-dd в три переменных d,m,y
local d,m,y = d:match('^%s*(%d%d?)[/.]([01]?%d)[/.](%-?%d+)')
if not d then y,m,d = D:match('^%s*(%-?%d+)[-\\]0*(1?%d)[-\\]0*(%d+)') end
return tonumber(d),tonumber(m),tonumber(y)
end
local function Cmp(a,b)--Сравнивает две даты, результат соответственно -1, 0 или 1
local d1,m1,y1 = GetDate(a)
local d2,m2,y2 = GetDate(b)
return d1 and d2 and (--nil, если формат не опознан
y1==y2 and (
m1==m2 and (
d1==d2 and 0 or d1<d2 and -1 or 1
) or m1<m2 and -1 or 1
) or y1<y2 and -1 or 1
)
end
local function Yyyymmdd(r)--Переводит русскую дату в YYYY,MM,DD
local d, m, y, M = mw.ustring.match(r, "^%s*(%d%d?)%s+([а-яА-Я]+)%s+(%d+)")
if not m then return nil end
m = mw.ustring.lower(m)
--тупо перебор
for i = 1, 12 do
if m == monthg[i] then
M = i
break
end
end
if not M then
return nil
end
return tonumber(y), M, tonumber(d)
end
local p = {}
p = {
ifdate=function(f)-- Для шаблона "Если дата", имитирует старое поведение
-- Аргументы передаются шаблону
return f:getParent().args[ mw.ustring.match(frame.args[1],"^[ %d.%-−%()]*$") and 2 or 3 ]
end;
DecodeDate = DecodeDate;
Diffy = Diffy;
Year0 = Year0;
GetDate = GetDate;
Cmp = Cmp;
Yyyymmdd = Yyyymmdd;
diffy = function(f)-- принимает параметры #invoke в виде двух строк-дат
local d1,m1,y1=DecodeDate(f.args[1]);
local d0,m0,y0=DecodeDate(f.args[2])
return Diffy(d1,m1,y1,d0,m0,y0)
end;
monthg=function(f) return monthg[ f.args[1] or f:getParent().args[1] ] end;--realmonth
persdate=function(f)-- Для шаблона Персона/Дата;{{#invoke:dates|persdate|nocat={{NAMESPACE}}}}
local frame=f:getParent();
local catpref,mo,d,d2={['Рождения']='Родившиеся',['Смерти']='Умершие'}, frame.args[1],frame.args[2],frame.args[3]
local cat, j,m,y,oj,om,oy,tail, j2,m2,y2, age = ''
if d then
j,m,y,oj,om,oy,tail=DecodeDate(d:gsub('−','-'));
if not (j or y) then
return (frame.args.nocat and d or d..'[[Category:Википедия:Статьи с ручной викификацией дат в карточке]]')
end
end;
if d2 then
j2,m2,y2 = DecodeDate(d2:gsub('−','-'));
end;
return table.concat{
FormDate(j,m,y,oj,om,oy,mo),
( (frame.args['nopersoncat'] or '')~='' or (f.args['nocat'] or '')~='' ) and '' or table.concat{
'[[Category:Персоналии по алфавиту]]',
j and string.format('[[Category:%s %i %s]]',catpref[mo],j,monthg[m]) or '',
y and string.format('[[Category:%s в %s]]',catpref[mo],y,Year0(y,'году')) or ''
},--/table.concat внутр.
(function(F)--возраст
if not F then return '' end;
local n=F();
return n and string.format(" (%i %s)%s",
n,
mw.getLanguage('ru'):plural(n,'год','года','лет'),
n>150 and '[[Category:Википедия:Статьи о персоналиях с большим текущим возрастом]]' or ''
) or ''
end)( ({
['Рождения']=function()
local now=os.date('*t');
if (not d2 or d2=='') and j and m and y then
return Diffy(now.day,now.month,now.year,j,m,y)
end
end,
['Смерти']=function()
return j and m and y and j2 and m2 and y2 and Diffy(j,m,y,j2,m2,y2);
end,
})[mo] ),--конец вызова функции возраста
tail or '',
cat
}--/table.concat внеш.
end;
formdate=function(f) -- Формирует дату по 3--6 параметрам #invoke или шаблона
--не использовать с пустыми аргументами
if (f.args[1] or '')~='' and (f.args[2] or '')~='' or (f.args[3] or '')~='' then
return FormDate(f.args[1],f.args[2],f.args[3],f.args[4],f.args[5],f.args[6],f.args['m'])
else
local tf=f:getParent();
return FormDate(tf.args[1],tf.args[2],tf.args[3],tf.args[4],tf.args[5],tf.args[6],tf.args['m'])
end
end;
cmp=function(f)--Сравнивает две даты, результат соответственно -1, 0 или 1
return Cmp(f.args[1],f.args[2])
end;
G2J=function(f)--перевод григорианских дат в юлианские, возврат DD.MM.YYYY
--Не знает про 15 октября 1582 года, не работает до нашей эры и после ???99 года
--Если есть второй аргумент, преобразует только ДО этой даты включительно
--Если есть третий аргумент, результат форматирует под Персона/Дата
local d,m,y=GetDate(f.args[1])
if f.args[2] and Cmp(f.args[1],f.args[2])==1 then
return string.format("%i.%i.%i",d,m,y)
end
local shift=math.floor(y/100)-math.floor(y/400)-2
if d-shift>0 then
return f.args[3] and string.format("%i.%i.%i (%i)",d,m,y,d-shift)
or string.format("%i.%i.%i",d-shift,m,y)
else
if m==1 then
return f.args[3]
and string.format("%i.1.%i (%i.12.%i)",d,y,31+d-shift,y-1)
or string.format("%i.12.%i",31+d-shift,y-1)
elseif m==3 then
return f.args[3] and string.format("%i.3.%i (%i.2)", d,y,
(y%4==0 and 29 or 28)+d-shift-(y%100==0 and y%400~=0 and 1 or 0)
)
or string.format("%i.2.%i",
(y%4==0 and 29 or 28)+d-shift-(y%100==0 and y%400~=0 and 1 or 0)
,y)
else
return f.args[3] and string.format(
"%i.%i.%i (%i.%i)", d,m,y, monthd[m-1]+d-shift,m-1
)
or string.format("%i.%i.%i",monthd[m-1]+d-shift,m-1,y)
end
end
end;
-- Переводит русскую дату в YYYY-MM-DD. Возвращает входное значение, если дата уже в этом формате
yyyymmdd = function(f)
local date, hourmin = f.args[1]
if mw.ustring.match(date, "^%s*%d+\-%d+\-%d+") then
return date
end
hourmin = mw.ustring.match(date, "%s+%d+:%d+$")
local y, m, d = Yyyymmdd(date)
if not y then
return '<span class="error">Ошибка: некорректный формат даты.</span>'
end
return string.format('%4i-%02i-%02i', y, m, d) .. (hourmin or '')
end
}
function table.val_to_str ( v )
if "string" == type( v ) then
v = string.gsub( v, "\n", "\\n" )
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
return "'" .. v .. "'"
end
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
else
return "table" == type( v ) and table.tostring( v ) or
tostring( v )
end
end
function table.key_to_str ( k )
if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
return k
else
return "[" .. table.val_to_str( k ) .. "]"
end
end
function table.tostring( tbl )
local result, done = {}, {}
for k, v in ipairs( tbl ) do
table.insert( result, table.val_to_str( v ) )
done[ k ] = true
end
for k, v in pairs( tbl ) do
if not done[ k ] then
table.insert( result,
table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
end
end
return "{" .. table.concat( result, "," ) .. "}"
end
local function parseISO8601Date(str)
local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
local Y, M, D = mw.ustring.match( str, pattern )
return tonumber(Y), tonumber(M), tonumber(D)
end
local function parseISO8601Time(str)
local pattern = "T(%d+):(%d+):(%d+)%Z"
local H, M, S = mw.ustring.match( str, pattern)
return tonumber(H), tonumber(M), tonumber(S)
end
local function parseISO8601Offset(str)
if str:sub(-1)=="Z" then return 0,0 end -- ends with Z, Zulu time
-- matches ±hh:mm, ±hhmm or ±hh; else returns nils
local pattern = "([-+])(%d%d):?(%d?%d?)$"
local sign, oh, om = mw.ustring.match( str, pattern)
sign, oh, om = sign or "+", oh or "00", om or "00"
return tonumber(sign .. oh), tonumber(sign .. om)
end
function p.parseISO8601(str)
if 'table'==type(str) then
if str.args and str.args[1] then
str = '' .. str.args[1]
else
return 'unknown argument type: ' .. type( str ) .. ': ' .. table.tostring( str )
end
end
local Y,M,D = parseISO8601Date(str)
local h,m,s = parseISO8601Time(str)
local oh,om = parseISO8601Offset(str)
return tonumber(os.time({year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s}))
end
local g2uBoundary1 = p.parseISO8601('1582-10-15T00:00:00Z')
local g2uBoundary2 = p.parseISO8601('1700-03-12T00:00:00Z')
local g2uBoundary3 = p.parseISO8601('1800-03-13T00:00:00Z')
local g2uBoundary4 = p.parseISO8601('1900-03-14T00:00:00Z')
local g2uBoundary5 = p.parseISO8601('1918-01-26T00:00:00Z') -- декрет Ленина
-- Передаваемое время обязано быть по Григорианскому календарю (новому стилю)
function p.formatWiki( time, infocardClass, categoryNamePrefix )
if 'table'==type( time ) then
if time.args and time.args[1] then
time = tonumber( time.args[1] )
else
return 'unknown argument type: ' .. type( time ) .. ': ' .. table.tostring( time )
end
end
local t = os.date("*t", time)
if time < g2uBoundary1 then
-- выводим просто юлианский календарь. Задавать тут григорианский некорректно
return p.formatWikiImpl( t, t, infocardClass, categoryNamePrefix )
end
-- Специальные даты
if t.year == 1700 and t.month == 3 and t.day == 11 then
return p.formatWikiImpl( {year=1700, month=2, day=29}, t, infocardClass, categoryNamePrefix)
end
if t.year == 1800 and t.month == 3 and t.day == 12 then
return p.formatWikiImpl( {year=1800, month=2, day=29}, t, infocardClass, categoryNamePrefix )
end
if t.year == 1900 and t.month == 3 and t.day == 13 then
return p.formatWikiImpl( {year=1900, month=2, day=29}, t, infocardClass, categoryNamePrefix )
end
if g2uBoundary1 <= time and time < g2uBoundary2 then
return p.formatWikiImpl( os.date("*t", time - 10 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
end
if g2uBoundary2 <= time and time < g2uBoundary3 then
return p.formatWikiImpl( os.date("*t", time - 11 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
end
if g2uBoundary3 <= time and time < g2uBoundary4 then
return p.formatWikiImpl( os.date("*t", time - 12 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
end
if g2uBoundary4 <= time and time < g2uBoundary5 then
return p.formatWikiImpl( os.date("*t", time - 13 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
end
--только Григорианский календарь
return p.formatWikiImpl( t, t, infocardClass, categoryNamePrefix )
end
local function ternary ( cond , T , F )
if cond then return T else return F end
end
local nominativeMonthes = {'январь', 'февраль', 'март', 'апрель', 'май', 'июнь',
'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'}
local genitivusMonthes = {'января', 'февраля', 'марта', 'апреля', 'мая', 'июня',
'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'}
local function nominativeYear( year, nolinks )
if ( year >= 0 ) then
return nolinks and year or '[[' .. year .. ' год|' .. year .. ']]'
else
return nolinks and ( 0 - year ) .. ' до н. э.' or '[[' .. ( 0 - year ) .. ' год до н. э.|' .. ( 0 - year ) .. ' до н. э.]]'
end
end
local function inYear( year )
if ( year >= 0 ) then
return '' .. year .. ' году'
else
return '' .. ( 0 - year) .. ' году до н. э.'
end
end
function p.formatWikiImpl( t1, t2, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
local nd = t2.day;
local nm = t2.month;
local ny = t2.year;
local od = ternary ( t1.day ~= t2.day , t1.day, nil );
local om = ternary ( t1.month ~= t2.month , t1.month, nil );
local oy = ternary ( t1.year ~= t2.year , t1.year, nil );
if leftBracket == nil then
leftBracket = '('
end
if rightBracket == nil then
rightBracket = ')'
end
local JulianComment = function(s)
return tostring(mw.html.create("abbr")
:attr("title","по юлианскому календарю")
:wikitext(s)
:done())
end
local template =
(nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "") ..
(od ~= nil and "4" or "") .. (om ~= nil and "5" or "") .. (oy ~= nil and "6" or "")
local datePart = '<span class="nowrap">'
if (template == "12") then
datePart = datePart .. string.format( nolinks and "%d %s" or "[[%d %s]]",
nd, genitivusMonthes[nm] )
elseif (template == "23") then
datePart = datePart .. string.format( "%s %s",
nominativeMonthes[nm], nominativeYear( ny, nolinks ) )
elseif (template == "3") then
datePart = datePart .. nominativeYear( ny, nolinks )
elseif (template == "123") then
datePart = datePart .. string.format( nolinks and "%d %s %s" or "[[%d %s]] %s",
nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
elseif (template == "124") then
if nolinks then
datePart = datePart .. JulianComment(string.format( "%d", od )
).. string.format( " " .. leftBracket .. "%d" .. rightBracket .. " %s",
nd, genitivusMonthes[nm] )
else
datePart = datePart .. JulianComment(string.format( "%d", od )
).. string.format( " [[%d %s|" .. leftBracket .. "%d" .. rightBracket .. " %s]]",
nd, genitivusMonthes[nm], nd, genitivusMonthes[nm] )
end
elseif (template == "1234") then
if nolinks then
datePart = datePart .. JulianComment(string.format( "%d", od )
).. string.format( " |" .. leftBracket .. "%d" .. rightBracket .. " %s %s",
nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
else
datePart = datePart .. JulianComment(string.format( "%d", od )
).. string.format( " [[%d %s|" .. leftBracket .. "%d" .. rightBracket .. " %s]] %s",
nd, genitivusMonthes[nm], nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
end
elseif (template == "1245") then
datePart = datePart .. JulianComment(string.format( "%d %s", od, genitivusMonthes[om] )
).. string.format(" " .. leftBracket .. (nolinks and "%d %s" or "[[%d %s]]") .. rightBracket .. "", nd, genitivusMonthes[nm] )
elseif (template == "12345") then
datePart = datePart .. JulianComment(string.format( "%d %s", od, genitivusMonthes[om] )
).. string.format(" " .. leftBracket .. (nolinks and "%d %s" or "[[%d %s]]") .. rightBracket .. " %s", nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
elseif (template == "123456") then
datePart = datePart .. JulianComment(string.format( "%d %s %d", od, genitivusMonthes[om], oy ))
.. '</span> <span class="nowrap">'
.. string.format(" " .. leftBracket .. (nolinks and "%d %s %s" or "[[%d %s]] %s") .. rightBracket , nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) )
else
datePart = datePart .. 'формат неверен'
end
datePart = datePart .. '</span>'
local infocardTemplate =
(nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "")
if infocardClass then
if (infocardTemplate == "123") then
datePart = datePart .. string.format('<span style="display:none">(<span class="%s">%04d-%02d-%02d</span>)</span>', infocardClass , ny , nm , nd )
elseif (infocardTemplate == "23") then
datePart = datePart .. string.format('<span style="display:none">(<span class="%s">%04d-%02d</span>)</span>', infocardClass , ny , nm )
elseif (infocardTemplate == "3") then
datePart = datePart .. string.format('<span style="display:none;">(<span class="%s">%04d</span>)</span>', infocardClass , ny )
end
end
if categoryNamePrefix then
if ( nd ~= nil and nm ~= nil) then
datePart = datePart .. '[[Category:' .. categoryNamePrefix .. ' ' .. nd .. ' ' .. genitivusMonthes[nm] .. ']]'
end
if ( ny ~= nil) then
datePart = datePart .. '[[Category:' .. categoryNamePrefix .. ' в ' .. inYear( ny ) .. ']]'
end
end
return datePart
end
return p
902bb6a9ef5ce12ad4cfa19f3d2c964d7e092df7
Шаблон:Lang-en
10
62
122
121
2025-01-25T21:00:28Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<nowiki />[[английский язык|англ.]] {{lang-en2|{{{1}}}}}<noinclude>
{{doc|Lang/doc}}
</noinclude>
6fcc1d4dc63f133033671bf27e48a6e701e126cb
Шаблон:Lang-en2
10
63
124
123
2025-01-25T21:00:28Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{langi|en|{{{1}}}}}<noinclude>
{{doc|Lang/doc}}
</noinclude>
0471cf4d45a13ece481915d5c3e55db65d6aca04
Модуль:Color contrast
828
64
126
125
2025-01-25T21:00:28Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--
-- This module implements
-- {{Color contrast ratio}}
-- {{Greater color contrast ratio}}
-- {{ColorToLum}}
-- {{RGBColorToLum}}
--
local p = {}
local HTMLcolor = mw.loadData( 'Module:Color contrast/colors' )
local function sRGB ( v )
if (v <= 0.03928) then
v = v / 12.92
else
v = math.pow((v+0.055)/1.055, 2.4)
end
return v
end
local function rgbdec2lum( R, G, B )
if ( 0 <= R and R < 256 and 0 <= G and G < 256 and 0 <= B and B < 256 ) then
return 0.2126 * sRGB(R/255) + 0.7152 * sRGB(G/255) + 0.0722 * sRGB(B/255)
else
return ''
end
end
local function hsl2lum( h, s, l )
if ( 0 <= h and h < 360 and 0 <= s and s <= 1 and 0 <= l and l <= 1 ) then
local c = (1 - math.abs(2*l - 1))*s
local x = c*(1 - math.abs( math.fmod(h/60, 2) - 1) )
local m = l - c/2
local r, g, b = m, m, m
if( 0 <= h and h < 60 ) then
r = r + c
g = g + x
elseif( 60 <= h and h < 120 ) then
r = r + x
g = g + c
elseif( 120 <= h and h < 180 ) then
g = g + c
b = b + x
elseif( 180 <= h and h < 240 ) then
g = g + x
b = b + c
elseif( 240 <= h and h < 300 ) then
r = r + x
b = b + c
elseif( 300 <= h and h < 360 ) then
r = r + c
b = b + x
end
return rgbdec2lum(255*r, 255*g, 255*b)
else
return ''
end
end
local function color2lum( c )
if (c == nil) then
return ''
end
-- whitespace
c = c:match( '^%s*(.-)[%s;]*$' )
-- lowercase
c = c:lower()
-- first try to look it up
local L = HTMLcolor[c]
if (L ~= nil) then
return L
end
-- convert from hsl
if mw.ustring.match(c,'^hsl%([%s]*[0-9][0-9%.]*[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local h, s, l = mw.ustring.match(c,'^hsl%([%s]*([0-9][0-9%.]*)[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return hsl2lum(tonumber(h), tonumber(s)/100, tonumber(l)/100)
end
-- convert from rgb
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*%)$')
return rgbdec2lum(tonumber(R), tonumber(G), tonumber(B))
end
-- convert from rgb percent
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return rgbdec2lum(255*tonumber(R)/100, 255*tonumber(G)/100, 255*tonumber(B)/100)
end
-- remove leading # (if there is one) and whitespace
c = mw.ustring.match(c, '^[%s#]*([a-f0-9]*)[%s]*$')
-- split into rgb
local cs = mw.text.split(c or '', '')
if( #cs == 6 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[2])
local G = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[4])
local B = 16*tonumber('0x' .. cs[5]) + tonumber('0x' .. cs[6])
return rgbdec2lum(R, G, B)
elseif ( #cs == 3 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[1])
local G = 16*tonumber('0x' .. cs[2]) + tonumber('0x' .. cs[2])
local B = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[3])
return rgbdec2lum(R, G, B)
end
-- failure, return blank
return ''
end
function p._greatercontrast(args)
local bias = tonumber(args['bias'] or '0') or 0
local v1 = color2lum(args[1] or '')
local c2 = args[2] or '#FFFFFF'
local v2 = color2lum(c2)
local c3 = args[3] or '#000000'
local v3 = color2lum(c3)
local ratio1 = 0;
local ratio2 = 0;
if (type(v1) == 'number' and type(v2) == 'number') then
ratio1 = (v2 + 0.05)/(v1 + 0.05)
ratio1 = (ratio1 < 1) and 1/ratio1 or ratio1
end
if (type(v1) == 'number' and type(v3) == 'number') then
ratio2 = (v3 + 0.05)/(v1 + 0.05)
ratio2 = (ratio2 < 1) and 1/ratio2 or ratio2
end
return (ratio1 + bias > ratio2) and c2 or c3
end
function p._ratio(args)
local v1 = color2lum(mw.text.unstripNoWiki(args[1] or ''))
local v2 = color2lum(mw.text.unstripNoWiki(args[2] or ''))
if (type(v1) == 'number' and type(v2) == 'number') then
-- v1 should be the brighter of the two.
if v2 > v1 then
v1, v2 = v2, v1
end
return (v1 + 0.05)/(v2 + 0.05)
else
return args['error'] or '?'
end
end
function p._styleratio(args)
local style = (args[1] or ''):lower()
local bg, fg = 'white', '#202122'
local lum_bg, lum_fg = 1, 0.016
if args[2] then
local lum = color2lum(args[2])
if lum ~= '' then bg, lum_bg = args[2], lum end
end
if args[3] then
local lum = color2lum(args[3])
if lum ~= '' then fg, lum_fg = args[3], lum end
end
local slist = mw.text.split(style or '', ';')
for k = 1, #slist do
local s = slist[k]
local k, v = s:match( '^[%s]*([^:]-):([^:]-)[%s;]*$' )
k = k or ''
v = v or ''
if (k:match('^[%s]*(background)[%s]*$') or k:match('^[%s]*(background%-color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_bg = v, lum end
elseif (k:match('^[%s]*(color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_fg = v, lum end
end
end
if lum_bg > lum_fg then
return (lum_bg + 0.05)/(lum_fg + 0.05)
else
return (lum_fg + 0.05)/(lum_bg + 0.05)
end
end
function p.lum(frame)
return color2lum(frame.args[1] or frame:getParent().args[1])
end
function p.ratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._ratio(args)
end
function p.styleratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._styleratio(args)
end
function p.greatercontrast(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._greatercontrast(args)
end
return p
cce580326bee8eaf3c81df6c76c04a9a2909dfa2
Модуль:Color contrast/colors
828
65
128
127
2025-01-25T21:00:29Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
return {
aliceblue = 0.92880068253475,
antiquewhite = 0.84646951707754,
aqua = 0.7874,
aquamarine = 0.8078549208338,
azure = 0.97265264954166,
beige = 0.8988459998705,
bisque = 0.80732327372979,
black = 0,
blanchedalmond = 0.85084439608156,
blue = 0.0722,
blueviolet = 0.12622014321946,
brown = 0.098224287876511,
burlywood = 0.51559844533893,
cadetblue = 0.29424681085422,
chartreuse = 0.76032025902623,
chocolate = 0.23898526114557,
coral = 0.37017930872924,
cornflowerblue = 0.30318641994179,
cornsilk = 0.93562110372965,
crimson = 0.16042199953026,
cyan = 0.7874,
darkblue = 0.018640801980939,
darkcyan = 0.20329317839046,
darkgoldenrod = 0.27264703559993,
darkgray = 0.39675523072563,
darkgreen = 0.091143429047575,
darkgrey = 0.39675523072563,
darkkhaki = 0.45747326349994,
darkmagenta = 0.07353047651207,
darkolivegreen = 0.12651920884889,
darkorange = 0.40016167026524,
darkorchid = 0.13413142174857,
darkred = 0.054889674531132,
darksalmon = 0.40541471563381,
darkseagreen = 0.43789249325969,
darkslateblue = 0.065792846227988,
darkslategray = 0.067608151928044,
darkslategrey = 0.067608151928044,
darkturquoise = 0.4874606277449,
darkviolet = 0.10999048339343,
deeppink = 0.23866895828276,
deepskyblue = 0.44481603395575,
dimgray = 0.14126329114027,
dimgrey = 0.14126329114027,
dodgerblue = 0.27442536991456,
firebrick = 0.10724525535015,
floralwhite = 0.95922484825004,
forestgreen = 0.18920812076002,
fuchsia = 0.2848,
gainsboro = 0.71569350050648,
ghostwhite = 0.94311261886323,
gold = 0.69860877428159,
goldenrod = 0.41919977809569,
gray = 0.2158605001139,
green = 0.15438342968146,
greenyellow = 0.80609472611453,
grey = 0.2158605001139,
honeydew = 0.96336535554782,
hotpink = 0.34658438169715,
indianred = 0.21406134963884,
indigo = 0.03107561486337,
ivory = 0.99071270600615,
khaki = 0.77012343394121,
lavender = 0.80318750514521,
lavenderblush = 0.90172748631046,
lawngreen = 0.73905893124963,
lemonchiffon = 0.94038992245622,
lightblue = 0.63709141280807,
lightcoral = 0.35522120733135,
lightcyan = 0.94587293494829,
lightgoldenrodyellow = 0.93348351018297,
lightgray = 0.65140563741982,
lightgreen = 0.69091979956865,
lightgrey = 0.65140563741982,
lightpink = 0.58566152734898,
lightsalmon = 0.4780675225206,
lightseagreen = 0.35050145117042,
lightskyblue = 0.56195637618331,
lightslategray = 0.23830165007287,
lightslategrey = 0.23830165007287,
lightsteelblue = 0.53983888284666,
lightyellow = 0.98161818392882,
lime = 0.7152,
limegreen = 0.44571042246098,
linen = 0.88357340984379,
magenta = 0.2848,
maroon = 0.045891942324215,
mediumaquamarine = 0.49389703310801,
mediumblue = 0.044077780212328,
mediumorchid = 0.21639251153773,
mediumpurple = 0.22905858091648,
mediumseagreen = 0.34393112338131,
mediumslateblue = 0.20284629471622,
mediumspringgreen = 0.70704308194184,
mediumturquoise = 0.5133827926448,
mediumvioletred = 0.14371899849357,
midnightblue = 0.02071786635086,
mintcream = 0.97834604947588,
mistyrose = 0.82183047859185,
moccasin = 0.80083000991567,
navajowhite = 0.76519682342785,
navy = 0.015585128108224,
oldlace = 0.91900633405549,
olive = 0.20027537200568,
olivedrab = 0.22593150951929,
orange = 0.4817026703631,
orangered = 0.25516243753416,
orchid = 0.31348806761439,
palegoldenrod = 0.78792647887614,
palegreen = 0.77936759006353,
paleturquoise = 0.76436077921714,
palevioletred = 0.28754994117889,
papayawhip = 0.87797100199835,
peachpuff = 0.74905589878251,
peru = 0.30113074877936,
pink = 0.63271070702466,
plum = 0.45734221587969,
powderblue = 0.68254586500605,
purple = 0.061477070432439,
rebeccapurple = 0.07492341159447,
red = 0.2126,
rosybrown = 0.32319457649407,
royalblue = 0.16663210743188,
saddlebrown = 0.097922285020521,
salmon = 0.36977241527596,
sandybrown = 0.46628543696283,
seagreen = 0.19734199706275,
seashell = 0.92737862206922,
sienna = 0.13697631337098,
silver = 0.52711512570581,
skyblue = 0.55291668518184,
slateblue = 0.14784278062136,
slategray = 0.20896704076536,
slategrey = 0.20896704076536,
snow = 0.96533341834849,
springgreen = 0.73052306068529,
steelblue = 0.20562642207625,
tan = 0.48237604163921,
teal = 0.16996855778968,
thistle = 0.56818401093733,
tomato = 0.30638612719415,
turquoise = 0.5895536427578,
violet = 0.40315452986676,
wheat = 0.74909702820482,
white = 1,
whitesmoke = 0.91309865179342,
yellow = 0.9278,
yellowgreen = 0.50762957208707,
}
6ae47fdb24de4eed5ec26d203faf5341a388987b
Шаблон:Yesno-yes
10
66
130
129
2025-01-25T21:00:29Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{safesubst:<noinclude />yesno|{{{1}}}|yes={{{yes|yes}}}|no={{{no|no}}}|blank={{{blank|yes}}}|¬={{{¬|yes}}}|def={{{def|yes}}}}}<noinclude>
{{doc}}
</noinclude>
3792ff694708f98102e3a6d556abe73bedc29069
Шаблон:No-doc
10
67
132
131
2025-01-25T21:00:29Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#ifeq: {{SUBPAGENAME}} | doc
|| {{#if: {{#if: {{yesno|{{{nocat|}}}}} | x }}{{#switch: {{NAMESPACE}} | {{ns:10}} | {{ns:828}} = | x }}
|| {{{1|}}}
}}
}}<noinclude>{{doc}}</noinclude>
da013ca5b5f97f94bee392ff3a4488046f2ceac7
Модуль:Wikidata/Medals
828
68
134
133
2025-01-25T21:00:30Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local WDS = require( 'Module:WikidataSelectors' )
local moduleDate = require( 'Module:Wikidata/date' )
local awardsOrder = mw.ext.data.get( "Wikidata/awards order.tab" )
local p = {}
local config = {
--Hide award with key QID if there is a reward with value QID
absorption = {
Q16675272 = 'Q654471',
Q16481808 = 'Q8706404',
Q1948730 = 'Q178473',
Q1980962 = 'Q208167',
Q2032399 = 'Q2046996',
Q102183407 = 'Q103819965',
Q1262166 = 'Q80589',
Q749849 = 'Q1358055',
Q4287121 = 'Q4137462',
}
}
--Get string with dates from qualifiers table
local function datesFromQualifier( context, options, qualifierId )
local dates = {}
local qualifiers = options.qualifiers[ qualifierId ]
if qualifiers then
for _, qualifier in pairs( qualifiers ) do
if qualifier.datavalue then
local dateValue = moduleDate.formatDate( context, options, qualifier.datavalue.value )
if dateValue then
table.insert( dates, dateValue )
end
end
end
end
return table.concat( dates, ', ' )
end
--Property function for [[d:Property:P166]]
function p.formatProperty( context, options )
if ( not context ) then error( 'context not specified' ); end;
if ( not options ) then error( 'options not specified' ); end;
if ( not options.entityId ) then error( 'options.entityId missing' ); end;
local claims;
if options.property then -- TODO: Почему тут может не быть property?
claims = context.selectClaims( options, options.property );
end
if claims == nil then
return '' --TODO error?
end
-- Обход всех заявлений утверждения и с накоплением оформленых
-- предпочтительных заявлений в таблице.
local formattedData = {}
for i, claim in ipairs( claims ) do
if ( claim.mainsnak and
claim.mainsnak and
claim.mainsnak.datavalue and
claim.mainsnak.datavalue.type == 'wikibase-entityid'
) then
local valueId = claim.mainsnak.datavalue.value.id
local formattedStatement = context.formatStatement( options, claim )
-- здесь может вернуться либо оформленный текст заявления, либо строка ошибки, либо nil
if ( formattedStatement and formattedStatement ~= '' ) then
formattedStatement = '<span class="wikidata-claim" data-wikidata-property-id="' .. string.upper( options.property ) .. '" data-wikidata-claim-id="' .. claim.id .. '">' .. formattedStatement .. '</span>'
table.insert( formattedData, {
id = valueId,
html = formattedStatement,
} )
end
end
end
-- Удаление дублей (медаль + звание -> звание)
for i, awardData in ipairs( formattedData ) do
local isAbsorptionFound = false
if config.absorption[ awardData.id ] then
local absorptionAwardId = config.absorption[ awardData.id ]
for _, absorptionAwardData in ipairs( formattedData ) do
if absorptionAwardData.id == absorptionAwardId then
isAbsorptionFound = true
break
end
end
end
if isAbsorptionFound then
table.remove( formattedData, i )
end
end
-- Сортировка медалей по старшинству
local orderedData = {}
local lastValue;
if ( type (awardsOrder) == 'table' ) then
-- Если не отсохла stuctured data
for i, awardFields in ipairs( awardsOrder.data ) do
local awardOrder = awardFields[ 1 ]
if awardOrder == '-' then
-- separator
if lastValue ~= '-' then
table.insert( orderedData, '<br>' )
lastHeight = nil
end
else
for k, awardData in ipairs( formattedData ) do
if awardOrder == awardData.id and not awardData.used then
table.insert( orderedData, awardData.html )
formattedData[ k ].used = true
end
end
end
end
end
for i, awardData in ipairs( formattedData ) do
if not awardData.used then
table.insert( orderedData, awardData.html )
end
end
local lastHeight
for i, awardHtml in ipairs( orderedData ) do
local height = mw.ustring.match( awardHtml, 'x%d+px' )
if height and lastHeight and height ~= lastHeight then
table.insert( orderedData, i, '<br>' )
end
lastHeight = height
end
-- создание текстовой строки со списком оформленых заявлений из таблицы
local out = mw.text.listToText( orderedData, options.separator, options.conjunction )
if out ~= '' then
if options.before then
out = options.before .. out
end
if options.after then
out = out .. options.after
end
end
return out
end
local function getImageFromProperty( entityId, propertyId )
local imageClaims = WDS.load( entityId, propertyId )
if imageClaims and #imageClaims > 0 then
for _, claim in ipairs( imageClaims ) do
if claim.type == 'statement' and claim.mainsnak.snaktype == 'value' then
return claim.mainsnak.datavalue.value
end
end
end
return nil
end
-- Получение изображения (планки или иконки) и его размера
function p.getImageFromEntity( entityId, actualDate )
if type( entityId ) ~= "string" then
entityId = entityId.id
end
local image = nil
local size = 'x17px'
local border = false
-- получение изображения планки из элемента
image = getImageFromProperty( entityId, 'P2425' )
if image then
border = true
end
-- получение иконки из элемента
if not image then
image = getImageFromProperty( entityId, 'P2910' )
if image then
size = '40x40px'
end
end
return image, size, border
end
--Value function for [[d:Property:P166]]
function p.formatValue( context, options, statement )
local entityId = statement.id
if not entityId then
return statement
end
local label = mw.wikibase.getLabel( entityId )
local image, size, border = p.getImageFromEntity( entityId )
local recipientCategory = ''
if not options.nocat and options.nocat ~= '' then
recipientCategory = context.extractCategory( { category = 'P7084[P4224:Q24571879]' }, entityId )
if recipientCategory == '' then
recipientCategory = context.extractCategory( { category = 'P2517' }, entityId )
end
end
local dates = ''
if options.qualifiers then
local startDates = {}
dates = datesFromQualifier( context, options, 'P580' )
if dates ~= '' then
local endDates = datesFromQualifier( context, options, 'P582' )
if endDates and endDates ~= '' then
dates = dates .. ' — ' .. endDates
end
else
dates = datesFromQualifier( context, options, 'P585' )
end
if options.qualifiers.P27 then
mw.log('>>>>>>>>>>>>>')
for _, claim in ipairs( options.qualifiers.P27 ) do
if claim and claim.datavalue and claim.datavalue.value and claim.datavalue.value.id then
local categoryOptions = { category = 'P7084[P27:' .. claim.datavalue.value.id .. ']' }
recipientCategory = recipientCategory .. context.extractCategory( categoryOptions, entityId )
end
end
end
end
-- получение ссылки по идентификатору и вывод планки
if image then
local link = mw.wikibase.getSitelink( entityId )
local out = '[[File:' .. image
if border == true then
out = out .. '|border'
end
out = out .. '|' .. size .. '|link='
-- получение ссылки из родительского элемента
-- для степеней обычно только одна общая статья
if not link then
local partOfClaims = WDS.load( entityId, 'P361' ) -- часть от
if not partOfClaims or #partOfClaims == 0 then
partOfClaims = WDS.load( entityId, 'P279' ) -- подкласс от
end
if partOfClaims and #partOfClaims > 0 then
for _, claim in ipairs( partOfClaims ) do
if claim.type == 'statement' and claim.mainsnak.snaktype == 'value' then
link = mw.wikibase.getSitelink( claim.mainsnak.datavalue.value.id )
if link then
break
end
end
end
end
end
if link then
out = out .. link
else
out = out .. 'd:' .. entityId
end
if label then
out = out .. '|' .. label
end
out = out .. ']]'
out = out .. recipientCategory
return out
end
local out = context.formatValueDefault( context, options, statement )
if out and out ~= '' then
if dates ~= '' then
out = out .. ' (' .. dates .. ')'
end
return '<span style="display:inline-block; text-align:left>' .. out .. recipientCategory .. '</span>'
end
return ''
end
--Table for documentation
function p.renderDoc()
local out = {}
for i, awardFields in ipairs( awardsOrder.data ) do
local awardId = awardFields[ 1 ]
local link = '[[d:' .. awardId .. '|' .. awardId .. ']]'
if i == 351 then
-- limits
table.insert( out, '| … || … || … || … || …' )
elseif i > 351 and i < #awardsOrder.data then
-- do nothing
elseif awardId == '-' then
-- separator
table.insert( out, '|' .. i .. '|| colspan="3" | ----' )
else
local image, size, border = p.getImageFromEntity( awardId )
if image then
image = '[[File:' .. image
if border == true then
image = image .. '|border'
end
image = image .. '|' .. size .. ']]'
else
image = ''
end
local label = mw.wikibase.getLabel( awardId ) or ''
local article = mw.wikibase.getSitelink( awardId )
if article then
if label == '' then
label = article
end
label = '[[' .. article .. '|' .. label .. ']]'
end
local countryStatements = mw.wikibase.getBestStatements( awardId, 'P17' )
local countries = {}
if countryStatements then
for _, statement in ipairs( countryStatements ) do
if statement.mainsnak.datavalue and
statement.mainsnak.datavalue.type == 'wikibase-entityid'
then
local countryId = statement.mainsnak.datavalue.value.id
table.insert( countries, mw.wikibase.getLabel( countryId ) )
end
end
end
table.insert( out, '|' .. i .. '||' .. link .. '||' .. image ..
'||' .. label .. '||' .. table.concat( countries, ', ' ) )
end
end
return '{| class="wikitable"\n' ..
'! # !! Элемент !! Планка !! Название !! Государство\n|-\n' ..
table.concat( out, '\n|-\n' ) ..
'\n|}'
end
return p
4de64e0e2181e8a4487f3e18da893fca9f92660d
Модуль:Separated entries
828
69
136
135
2025-01-25T21:00:30Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- This module takes positional parameters as input and concatenates them with
-- an optional separator. The final separator (the "conjunction") can be
-- specified independently, enabling natural-language lists like
-- "foo, bar, baz and qux".
local compressSparseArray = require('Module:TableTools').compressSparseArray
local p = {}
function p._main(args)
local separator = args.separator
-- Decode (convert to Unicode) HTML escape sequences, such as " " for space.
and mw.text.decode(args.separator) or ''
local conjunction = args.conjunction and mw.text.decode(args.conjunction) or separator
-- Discard named parameters.
local values = compressSparseArray(args)
return mw.text.listToText(values, separator, conjunction)
end
local function makeInvokeFunction(separator, conjunction)
return function (frame)
local args = require('Module:Arguments').getArgs(frame)
args.separator = separator or args.separator
args.conjunction = conjunction or args.conjunction
return p._main(args)
end
end
p.main = makeInvokeFunction()
p.br = makeInvokeFunction('<br />')
p.newline = makeInvokeFunction('\n')
p.comma = makeInvokeFunction(mw.message.new('comma-separator'):plain())
return p
33a68f0a46d62c42b6523a548f0f881e82ecfe58
Шаблон:Флагификация/Германия
10
70
138
137
2025-01-25T21:00:30Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{ {{{1<noinclude>|флагификация/флаг</noinclude>}}}
| alias = Германия
| flag alias = Flag of Germany.svg
| flag alias-империя = Flag of the German Empire.svg
| flag alias-1871 = Flag of the German Empire.svg
| flag alias-1919 = Flag of Germany (2-3).svg
| flag alias-1933-1 = National flag of Germany 1933-1935.svg
| flag alias-1933 = Flag of German Reich (1935–1945).svg
| flag alias-1946 = Flag of Germany (1946-1949).svg
| flag alias-Берлин = Flag of Berlin.svg
| flag alias-ГДР = Flag of East Germany.svg
| flag alias-1938 = War Ensign of Germany 1938-1945.svg
| flag alias-ВМФ = Naval Ensign of Germany.svg
| flag alias-1892 = Kaiserliche Kriegsflagge (1892).png
| flag alias-1921 = War Ensign of Germany (1921–1933).svg
| var1 = империя
| var2 = 1871
| var3 = 1919
| var4 = 1933-1
| var5 = 1933
| var6 = 1946
| var7 = Берлин
| var8 = ГДР
| var9 = 1938
| var10 = ВМФ
| var11 = 1892
| var12 = 1921
| variant = {{{variant|}}}
| размер = {{{размер|}}}
}}
efa3b6861970635c792254f5da10e4efbc3ded5d
Шаблон:Флагификация/Великобритания
10
71
140
139
2025-01-25T21:00:31Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{ {{{1<noinclude>|флагификация/флаг</noinclude>}}}
| alias = Великобритания
| flag alias = Flag of the United Kingdom.svg
| flag alias-1707 = Union flag 1606 (Kings Colors).svg
| flag alias-1658 = Flag of the Commonwealth (1658-1660).svg
| flag alias-1651 = Flag of The Commonwealth.svg
| flag alias-1649 = Flag of the Commonwealth (1649-1651).svg
| flag alias-1606 = Union flag 1606 (Kings Colors).svg
| flag alias-ВМС = Naval Ensign of the United Kingdom.svg
| flag alias-торговый = Civil Ensign of the United Kingdom.svg
| flag alias-ВВС = Ensign of the Royal Air Force.svg
| flag alias-дипломатический = Government Ensign of the United Kingdom.svg
| flag alias-армия = Flag of the British Army.svg
| variant = {{{variant|}}}
<noinclude>
| var1 = 1707
| var2 = 1658
| var3 = 1651
| var4 = 1649
| var5 = 1606
| var6 = ВМС
| var7 = торговый
| var8 = ВВС
| var9 = дипломатический
| var10 = армия
</noinclude>
| размер = {{{размер|}}}
}}
4bf44640a433c2a79fdf1d0e148897cad36f0f4d
Шаблон:Tl
10
72
142
141
2025-01-25T21:00:31Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke: Template call code | withoutParams }}<noinclude>{{doc}}</noinclude>
61fe4d068895a5e7e5802767f5d7df71a7561c57
Шаблон:Str sub
10
73
144
143
2025-01-25T21:00:31Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{{{{|safesubst:}}}#invoke:String|sublength|s={{{1}}}|i={{{2|0}}}|len={{{3|0}}}}}</includeonly><noinclude>
{{doc}}
</noinclude>
3043790f8803e868cf6097b475fd58ba742887fe
Шаблон:Без начала
10
74
146
145
2025-01-25T21:00:31Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#ifeq:{{<includeonly>safesubst:</includeonly>Str_left|{{{1}}}|{{<includeonly>safesubst:</includeonly>#expr:{{<includeonly>safesubst:</includeonly>str len|{{{2}}}*}}-1}}}}*|{{{2}}}*|{{<includeonly>safesubst:</includeonly>Str_right|{{{1}}}|{{<includeonly>safesubst:</includeonly>#expr:{{<includeonly>safesubst:</includeonly>str len|{{{2}}}*}}-1}}}}|{{{1}}}}}<noinclude>{{doc}}</noinclude>
9fbca6f1fc236cb17fe77d76891e3f9c2afa2117
Шаблон:Str len
10
75
148
147
2025-01-25T21:00:31Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke:String|len|s={{{1|}}}}}<noinclude>
{{doc}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
95f10258d5214440d2706952656564f216c2e4cc
Шаблон:Str rightc
10
76
150
149
2025-01-25T21:00:31Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>Str sub|{{{1}}}|{{<includeonly>safesubst:</includeonly>#expr:{{<includeonly>safesubst:</includeonly>Str len|{{{1}}}}}-{{{2}}}}}|{{{2}}}}}<noinclude>{{doc}}</noinclude>
0401d500dcc2224d44867ba0ea1f6c0fbeb758a0
Модуль:Wikidata/url
828
77
152
151
2025-01-25T21:00:32Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local p = {}
local function formatLangRefs( options )
local langRefs = {}
if options.qualifiers and options.qualifiers.P407 then
for _, qualifier in ipairs( options.qualifiers.P407 ) do
if ( qualifier
and qualifier.datavalue
and qualifier.datavalue.type == 'wikibase-entityid' ) then
local qualifierId = qualifier.datavalue.value.id
local wbStatus, langRefCodeClaims = pcall( mw.wikibase.getBestStatements, qualifierId, 'P218' )
if wbStatus and langRefCodeClaims then
for _, claim in ipairs( langRefCodeClaims ) do
if ( claim.mainsnak
and claim.mainsnak.datavalue
and claim.mainsnak.datavalue.type == 'string' ) then
local langRefCode = claim.mainsnak.datavalue.value
table.insert( langRefs, options.frame:expandTemplate{ title = 'ref-' .. langRefCode } )
end
end
end
end
end
end
return table.concat( langRefs, '​' )
end
function p.formatUrlValue( context, options, value )
local moduleUrl = require( 'Module:URL' )
local langRefs = formatLangRefs( options )
if not options.length or options.length == '' then
options.length = math.max( 18, 25 - #langRefs )
end
return moduleUrl.formatUrlSingle( context, options, value ) .. langRefs
end
return p
4a9959f45666b35899729e561a73e0535c16e15e
Шаблон:Цвет/Вокалист.css
10
78
154
153
2025-01-25T21:00:32Z
Vallenland
2
1 версия импортирована
text
text/plain
.infobox-above,
.infobox-header,
.infobox-below {
background: #f0e68c;
}
@media screen {
html.skin-theme-clientpref-night .infobox-above,
html.skin-theme-clientpref-night .infobox-header,
html.skin-theme-clientpref-night .infobox-below {
background: #302a00;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox-above,
html.skin-theme-clientpref-os .infobox-header,
html.skin-theme-clientpref-os .infobox-below {
background: #302a00;
}
}
/*
[[Категория:Шаблоны:Подстраницы CSS]]
[[Категория:Шаблоны:Цвета по темам:Музыка|Вокалист.css]]
*/
2e2ee1ff27b701bb561598af95c43d81a92319bc
Модуль:Hash
828
79
156
155
2025-01-25T21:00:32Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
local getArgs = require('Module:Arguments').getArgs
local p = {}
local function inTable(table, value)
for k, v in pairs(table) do
if v == value then
return true
end
end
return false
end
function p.list(frame)
return table.concat(mw.hash.listAlgorithms(), '; ')
end
function p.main(frame)
local args = getArgs(frame, { frameOnly = true })
local algorithm
if not args[1] then
return '<span class="error">Не указана строка для хеширования.</span>'
end
if args[2] then
if not inTable(mw.hash.listAlgorithms(), args[2]) then
return '<span class="error">Алгоритм хеширования ' .. args[2] .. ' не поддерживается, или вы неточно указали его имя. Используйте функцию <kbd>mw.hash.listAlgorithms()</kbd> для получения списка доступных алгоритмов.</span>'
end
algorithm = args[2]
else
-- Алгоритм выбран из соображений быстродействия (см. [[:en:Fowler–Noll–Vo hash function]]),
-- 64-битная функция используется для уменьшения вероятности коллизий до пренебрежимо малой
-- величины. Возможно, есть лучшая опция — проверяйте.
algorithm = 'fnv164'
end
return mw.hash.hashValue(algorithm, args[1])
end
return p
5d18513e574435f191164695449a620b031f93ec
Шаблон:Lang-de
10
80
158
157
2025-01-25T21:00:33Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
[[Немецкий язык|нем.]] {{langi|de|{{{1}}}}}<noinclude>{{doc|Lang/doc}}</noinclude>
646eff5eb102894e6474a9c639b707a8ea39dc6e
Модуль:Wikidata:Dictionary/P424
828
81
160
159
2025-01-25T21:00:33Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
return {
Q143={'eo'},
Q150={'fr'},
Q188={'de'},
Q256={'tr'},
Q294={'is'},
Q328={'en'},
Q397={'la'},
Q652={'it'},
Q809={'pl'},
Q1321={'es'},
Q1412={'fi'},
Q1568={'hi'},
Q1571={'mr'},
Q1617={'ur'},
Q1860={'en'},
Q4627={'ay'},
Q5111={'ab'},
Q5137={'gu'},
Q5146={'pt'},
Q5218={'qu'},
Q5287={'ja'},
Q5885={'ta'},
Q6654={'hr'},
Q7026={'ca'},
Q7411={'nl'},
Q7737={'ru'},
Q7838={'sw'},
Q7850={'zh'},
Q7913={'ro'},
Q7918={'bg'},
Q7930={'mg'},
Q7979={'en-gb'},
Q8097={'te'},
Q8108={'ka'},
Q8447={'fr'},
Q8449={'es'},
Q8641={'yi'},
Q8748={'sq'},
Q8752={'eu'},
Q8765={'an'},
Q8785={'hy'},
Q8798={'uk'},
Q9027={'sv'},
Q9035={'da'},
Q9043={'no'},
Q9051={'lb'},
Q9056={'cs'},
Q9058={'sk'},
Q9063={'sl'},
Q9067={'hu'},
Q9072={'et'},
Q9078={'lv'},
Q9083={'lt'},
Q9091={'be'},
Q9129={'mis'},
Q9142={'ga'},
Q9166={'mt'},
Q9168={'fa'},
Q9176={'ko'},
Q9186={'zh-yue','yue'},
Q9199={'vi'},
Q9205={'km'},
Q9211={'lo'},
Q9217={'th'},
Q9228={'my'},
Q9237={'ms'},
Q9240={'id'},
Q9246={'mn'},
Q9252={'kk'},
Q9255={'ky'},
Q9260={'tg'},
Q9264={'uz'},
Q9267={'tk'},
Q9288={'he'},
Q9292={'az'},
Q9296={'mk'},
Q9299={'sr'},
Q9301={'sh'},
Q9303={'bs'},
Q9307={'gl'},
Q9309={'cy'},
Q9314={'gd'},
Q9610={'bn'},
Q10000={'nl'},
Q10134={'tlh'},
Q10179={'zu'},
Q10199={'diq'},
Q11059={'sa'},
Q11913={'bg'},
Q11918={'el'},
Q11920={'it'},
Q11921={'pt'},
Q12107={'br'},
Q12175={'gv'},
Q12237={'la'},
Q13198={'rcf'},
Q13199={'rm'},
Q13201={'rmy'},
Q13216={'za'},
Q13218={'xh'},
Q13238={'udm'},
Q13248={'hsb'},
Q13263={'ug'},
Q13267={'si'},
Q13275={'so'},
Q13286={'dsb'},
Q13293={'sma'},
Q13300={'nah'},
Q13307={'na'},
Q13310={'nv'},
Q13324={'min'},
Q13330={'mwl'},
Q13343={'mdf'},
Q13356={'mzn'},
Q13357={'fit'},
Q13358={'ruq'},
Q13359={'xmf'},
Q13389={'ba'},
Q13955={'ar'},
Q14185={'oc'},
Q14196={'af'},
Q14380={'sl'},
Q14549={'sco'},
Q15085={'pms'},
Q15087={'frp'},
Q17985={'ko'},
Q21117={'esu'},
Q22711={'pdc'},
Q23014={'pfl'},
Q25164={'nn'},
Q25167={'nb'},
Q25258={'fo'},
Q25285={'tt'},
Q25289={'kw'},
Q25355={'kl'},
Q25433={'nds'},
Q26245={'rue'},
Q27154={'stq'},
Q27175={'fy'},
Q27183={'ik'},
Q27683={'ace'},
Q27776={'ady'},
Q27811={'aa'},
Q28026={'ak'},
Q28224={'frr'},
Q28244={'am'},
Q28378={'anp'},
Q28602={'arc'},
Q29316={'roa-rup','rup'},
Q29401={'as'},
Q29507={'ast'},
Q29540={'bar'},
Q29561={'av'},
Q29919={'arz'},
Q29921={'iu'},
Q29952={'myv'},
Q30005={'ee'},
Q30007={'ext'},
Q30239={'zh'},
Q30319={'szl'},
Q31746={'lez'},
Q32145={'ksh'},
Q32641={'mis'},
Q32656={'dv'},
Q32704={'ve'},
Q32724={'vec'},
Q32747={'vep'},
Q32762={'fiu-vro','vro'},
Q32858={'vot'},
Q32979={'cho'},
Q33025={'bej'},
Q33081={'dz'},
Q33111={'co'},
Q33120={'bxr'},
Q33151={'bjn'},
Q33170={'ckt'},
Q33190={'bug'},
Q33202={'brh'},
Q33219={'map-bms'},
Q33239={'ceb'},
Q33243={'bm'},
Q33262={'ch'},
Q33265={'chy'},
Q33268={'bh','bho'},
Q33273={'ny'},
Q33281={'cbk-zam'},
Q33284={'bcl'},
Q33287={'gaa'},
Q33291={'fon'},
Q33295={'fj'},
Q33315={'hz'},
Q33348={'cv'},
Q33350={'ce'},
Q33357={'crh'},
Q33368={'lg'},
Q33375={'hak'},
Q33388={'chr'},
Q33390={'cr'},
Q33441={'fur'},
Q33454={'ff'},
Q33457={'gag'},
Q33475={'gan'},
Q33491={'ht'},
Q33509={'inh'},
Q33522={'kbd'},
Q33541={'kaa'},
Q33549={'jv'},
Q33552={'ks'},
Q33569={'haw'},
Q33573={'rw'},
Q33578={'ig'},
Q33583={'rn'},
Q33587={'ki'},
Q33617={'ho'},
Q33634={'xal'},
Q33657={'glk'},
Q33661={'mfe'},
Q33673={'kn'},
Q33690={'csb'},
Q33698={'liv'},
Q33702={'kg'},
Q33714={'krc'},
Q33720={'krj'},
Q33730={'arn'},
Q33754={'lmo'},
Q33786={'sid'},
Q33810={'or'},
Q33823={'ne'},
Q33845={'nap'},
Q33850={'nrm'},
Q33856={'pap'},
Q33864={'om'},
Q33879={'pag'},
Q33900={'ng'},
Q33947={'se'},
Q33954={'sg'},
Q33968={'os'},
Q33973={'scn'},
Q33976={'sc'},
Q33979={'new'},
Q33989={'srn'},
Q33997={'sd'},
Q34002={'su'},
Q34004={'sn'},
Q34011={'sm'},
Q34014={'ss'},
Q34015={'crs'},
Q34024={'pcd'},
Q34055={'tvl'},
Q34057={'tl'},
Q34094={'to'},
Q34119={'tyv'},
Q34124={'ti'},
Q34125={'tet'},
Q34128={'ty'},
Q34137={'tn'},
Q34138={'tum'},
Q34147={'vls'},
Q34159={'tpi'},
Q34208={'wbl'},
Q34219={'wa'},
Q34233={'ryu'},
Q34235={'ii'},
Q34247={'yai'},
Q34251={'tcy'},
Q34257={'wo'},
Q34271={'bo'},
Q34279={'war'},
Q34290={'wuu'},
Q34299={'sah'},
Q34311={'yo'},
Q34318={'tly'},
Q34327={'ts'},
Q34340={'st'},
Q35224={'io'},
Q35225={'peo'},
Q35452={'bi'},
Q35497={'grc'},
Q35499={'cu'},
Q35501={'prg'},
Q35722={'got'},
Q35744={'kri'},
Q35850={'ie'},
Q35853={'kab'},
Q35876={'gn'},
Q35934={'ia'},
Q35936={'ilo'},
Q35939={'jam'},
Q35963={'mis'},
Q35978={'hil'},
Q36094={'kr'},
Q36106={'lij'},
Q36109={'mai'},
Q36121={'pam'},
Q36126={'kv'},
Q36196={'lad'},
Q36206={'lbe'},
Q36212={'ltg'},
Q36217={'ln'},
Q36236={'ml'},
Q36280={'mh'},
Q36323={'pko'},
Q36350={'jbo'},
Q36368={'ku'},
Q36387={'mis'},
Q36392={'mo'},
Q36451={'mi'},
Q36455={'cdo'},
Q36495={'zh-min-nan','nan'},
Q36510={'el'},
Q36584={'olo'},
Q36699={'pis'},
Q36727={'pi'},
Q36730={'ota'},
Q36738={'nov'},
Q36748={'pnt'},
Q36811={'ckb'},
Q36850={'tw'},
Q36986={'vo'},
Q37041={'zh-classical','lzh'},
Q37059={'bpy'},
Q37178={'ine'},
Q38288={'diq'},
Q42365={'ang'},
Q44676={'en-ca'},
Q45041={'lez'},
Q46728={'hif'},
Q48183={'de'},
Q48952={'fa'},
Q53464={'hu'},
Q56240={'aeb'},
Q56318={'koi'},
Q56426={'ary'},
Q56475={'ha'},
Q56483={'lki'},
Q56499={'arq'},
Q56508={'sou'},
Q58172={'kk'},
Q58209={'ba'},
Q58215={'cv'},
Q58251={'az'},
Q58255={'tr'},
Q58635={'pa'},
Q58679={'sh'},
Q58680={'ps'},
Q58781={'rue'},
Q60786={'crh'},
Q60799={'ky'},
Q60819={'tt'},
Q60856={'ug'},
Q79633={'gag'},
Q79636={'kaa'},
Q102172={'li'},
Q131339={'als','gsw'},
Q146803={'lfn'},
Q155214={'id'},
Q169514={'sv'},
Q175482={'fi'},
Q177837={'ja'},
Q181037={'aln'},
Q181163={'da'},
Q182695={'mis'},
Q190551={'eo'},
Q191168={'cs'},
Q191769={'no'},
Q192582={'sk'},
Q199693={'ca'},
Q199698={'uk'},
Q199700={'ar'},
Q199864={'ro'},
Q199913={'he'},
Q200060={'et'},
Q200180={'vi'},
Q200183={'simple'},
Q200386={'sr','sr-ec','sr-el'},
Q202472={'lt'},
Q203488={'hr'},
Q206855={'ru'},
Q207260={'eu'},
Q208533={'sq'},
Q213434={'bat-smg','sgs'},
Q221444={'udm'},
Q225594={'sah'},
Q226150={'os'},
Q237409={'zea'},
Q242648={'eml'},
Q257829={'bqi'},
Q306626={'de-at'},
Q427715={'bn'},
Q497345={'vmf'},
Q511754={'tk'},
Q516137={'nds-nl'},
Q523014={'mus'},
Q547271={'cu'},
Q565074={'th'},
Q571001={'tpi'},
Q588620={'pam'},
Q595628={'oc'},
Q695526={'roa-tara'},
Q714826={'vo'},
Q718394={'is'},
Q722040={'hi'},
Q722243={'sw'},
Q728945={'lv'},
Q750553={'pt-br'},
Q766705={'af'},
Q824297={'mhr'},
Q837615={'ceb'},
Q841208={'gl'},
Q842341={'mk'},
Q844491={'ta'},
Q845993={'ms'},
Q846630={'cdo'},
Q846871={'br'},
Q848046={'te'},
Q848525={'cy'},
Q848974={'ka'},
Q856881={'myv'},
Q874555={'ml'},
Q875631={'ga'},
Q877583={'be'},
Q877685={'tl'},
Q880301={'frc'},
Q925661={'kv'},
Q928808={'dv'},
Q938216={'khw'},
Q940309={'szl'},
Q950058={'lb'},
Q966609={'su'},
Q1034940={'mrj'},
Q1047829={'bs'},
Q1047851={'nap'},
Q1055841={'vec'},
Q1058430={'scn'},
Q1066461={'ht'},
Q1067878={'ur'},
Q1071918={'ast'},
Q1110233={'wuu'},
Q1116066={'koi'},
Q1132977={'wa'},
Q1147071={'an'},
Q1148240={'yo'},
Q1154741={'ku'},
Q1154766={'io'},
Q1178461={'mdf'},
Q1190962={'zh-yue'},
Q1194341={'ru-sib'},
Q1211233={'als'},
Q1249553={'krc'},
Q1287192={'bpy'},
Q1291627={'new'},
Q1366643={'de-ch'},
Q1377618={'qu'},
Q1378484={'zh-classical'},
Q1389492={'pnb'},
Q1405077={'kj'},
Q1444686={'sco'},
};
c8444b1c598748668639bce6aaadca710aea0059
Шаблон:Doc
10
82
162
161
2025-01-25T21:00:33Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{doc/begin|{{SUBJECTSPACE}}:{{PAGENAME:{{{1|{{SUBJECTPAGENAME}}/doc}}}}}}}
{{#if: {{{1|}}}
| {{#ifexist: {{#if: {{NAMESPACE:{{{1}}}}} | {{{1}}} | {{SUBJECTSPACE}}:{{{1}}} }}
| {{{{{1}}}|{{{2|}}}|{{{3|}}}|{{{4|}}}|{{{5|}}}}}
| {{#ifexist: {{SUBJECTSPACE}}:{{{1}}}
| {{{{{1}}}|{{{2|}}}|{{{3|}}}|{{{4|}}}|{{{5|}}}}}
| {{Документировать|{{{1}}}}}
}}
}}
| {{#ifexist: {{SUBJECTPAGENAME}}/doc
| {{{{SUBJECTPAGENAME}}/doc}}
| {{Документировать|{{SUBJECTPAGENAME}}/doc}}
}}
}}
{{doc/end}}</includeonly><noinclude>
{{doc}}
</noinclude>
7298506ab2882f16fe7a52e0e080b2780b237bb9
Шаблон:Doc/begin
10
83
164
163
2025-01-25T21:00:33Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly><templatestyles src="Шаблон:Doc/styles.css" />
<div class="ts-doc-doc" id="doc">
<div class="ts-doc-header" id="Документация">
<div class="ts-doc-heading">Документация</div>
{{#if: {{{inline|}}} || {{Действия для страницы|lc={{{1}}}|nowatch=yes}} }}
</div>
<div class="ts-doc-content"></includeonly><noinclude>
{{doc}}
</noinclude>
c753f0a9f65d86707cdffaf93fb49c2c52daf92b
Шаблон:Doc/styles.css
10
84
166
165
2025-01-25T21:00:34Z
Vallenland
2
1 версия импортирована
text
text/plain
.ts-doc-doc {
background-color: var(--background-color-progressive-subtle, #eaf3ff);
border: 1px solid var(--border-color-content-added, #afb6e9);
clear: both;
margin-top: 1em;
}
/* Ctrl+F ":target" in [[MediaWiki:Common.css]] */
.ts-doc-doc sup.reference:target,
.ts-doc-doc ol.references li:target,
.ts-doc-doc .highlight-target:target,
.ts-doc-doc cite:target,
.ts-doc-doc span.citation:target {
background: var(--ruwiki-background-color-blue200, #cfe3ff);
}
.ts-doc-header {
align-items: center;
background: var(--ruwiki-background-color-blue200, #cfe3ff);
display: flex;
flex-wrap: wrap;
padding: .642857em 1em .5em;
overflow: hidden;
}
.ts-doc-header .ts-tlinks-tlinks {
margin-left: auto;
}
.ts-doc-content {
padding: .214286em 1em;
}
.ts-doc-content:after {
content: '';
clear: both;
display: block;
}
.ts-doc-heading {
display: inline-block;
padding-left: 2em;
background: url(//upload.wikimedia.org/wikipedia/commons/c/ca/OOjs_UI_icon_info.svg) center left no-repeat;
background-size: contain;
font-size: small;
min-height: 1.75em;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
}
@media screen {
html.skin-theme-clientpref-night .ts-doc-heading {
background-image: url(//upload.wikimedia.org/wikipedia/commons/c/c0/OOjs_UI_icon_info-invert.svg);
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .ts-doc-heading {
background-image: url(//upload.wikimedia.org/wikipedia/commons/c/c0/OOjs_UI_icon_info-invert.svg);
}
}
.ts-doc-content > *:first-child,
.ts-doc-footer > *:first-child {
margin-top: .5em;
}
.ts-doc-content > *:last-child,
.ts-doc-footer > *:last-child {
margin-bottom: .5em;
}
.ts-doc-footer {
background-color: var(--background-color-progressive-subtle, #eaf3ff);
border: 1px solid var(--border-color-content-added, #afb6e9);
padding: .214286em 1em;
margin-top: .214286em;
margin-bottom: .214286em;
font-style: italic;
}
@media (max-width: 719px) {
.ts-doc-header {
display: block;
}
.ts-doc-header .ts-tlinks-tlinks {
float: none;
}
}
/* [[Категория:Шаблоны:Подстраницы CSS]] */
be8d912472a37a6051bee114da86f913839e7ca0
Шаблон:Действия для страницы
10
85
168
167
2025-01-25T21:00:34Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<templatestyles src="Шаблон:Действия для страницы/styles.css" /><div style="{{#ifeq: {{yesno-yes|{{{right|}}}}} | yes || float:none; }}" class="ts-tlinks-tlinks mw-editsection-like plainlinks"><span class="mw-editsection-bracket">[</span><!--
-->{{join|separator=<span class="mw-editsection-divider"> &#124; </span>
|1={{#ifexist: {{#rel2abs: {{{lc|}}} }}
| {{#ifeq: {{{dislooklink|{{{noview|}}}}}} | yes || [[{{{lc}}}|просмотр]] }}
}}
|2={{#ifexist: {{#rel2abs: {{{lc|}}} }}
| [[Special:EditPage/{{#rel2abs: {{{lc}}} }}|править]]
}}
|3={{#ifexist: {{#rel2abs: {{{lc|}}} }}
| {{#ifeq: {{{dishistlink|{{{nohistory|}}}}}} | yes || [[Special:PageHistory/{{#rel2abs: {{{lc}}} }}|история]] }}
}}
|4={{#ifexist: {{#rel2abs: {{{lc|}}} }}
|
| [{{fullurl:{{#rel2abs: {{{lc}}} }}|action=edit&redlink=1}} создать]
}}
|5={{#ifeq: {{{diswatchlink|{{{nowatch|}}}}}} | yes || [{{fullurl:{{#rel2abs: {{{lc}}} }}|action=watch}} следить] }}
|6={{#ifeq: {{{disupdlink|{{{noupdate|}}}}}} | yes || {{очистить кэш|обновить|nocat=1}}</span> }}
}}<span class="mw-editsection-bracket">]</span></div><noinclude>
{{doc}}
</noinclude>
9ee2c9eed92e2ecc9377a7b9486ad8bc214a83d4
Шаблон:Действия для страницы/styles.css
10
86
170
169
2025-01-25T21:00:34Z
Vallenland
2
1 версия импортирована
text
text/plain
.ts-tlinks-tlinks {
font-weight: normal;
float: right;
line-height: inherit;
}
.ts-tlinks-tlinks .mw-editsection-divider {
display: inline;
}
/* [[Категория:Шаблоны:Подстраницы CSS]] */
a003e896d263c29e66d2246b210e5d73e577ea46
Шаблон:Doc/end
10
87
172
171
2025-01-25T21:00:34Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly></div>
</div><templatestyles src="Шаблон:Doc/styles.css" />{{#ifexpr: {{NAMESPACENUMBER}} mod 2 = 1 <!-- Например, [[Обсуждение MediaWiki:Robots.txt]] -->
| {{^|1em}}
| <div class="ts-doc-footer plainlinks">
{{#ifeq: {{str left|{{PAGENAME}}|9}}
| Песочница
|
| {{#ifeq: {{str rightc|{{PAGENAME}}|10}}
| /песочница
|
| Во избежание поломок страниц, использующих этот {{#ifeq: {{NAMESPACE}}
| Модуль
| модуль
| шаблон
}}, экспериментируйте в [[Википедия:Правка и тестирование шаблонов в песочнице|песочнице]] <small style="font-style:normal;">({{#ifexist: {{FULLPAGENAME}}/песочница
| [{{fullurl:{{FULLPAGENAME}}/песочница|action=edit}} редактировать] {{!}} [{{fullurl:Special:ComparePages|page1={{FULLPAGENAMEE}}&page2={{FULLPAGENAMEE}}/песочница}} разница] {{#ifexist: {{FULLPAGENAME}}/тесты | {{!}} [[{{FULLPAGENAME}}/тесты|тесты]] }}
| {{#ifeq: {{NAMESPACE}} | Модуль | [{{fullurl:{{FULLPAGENAME}}/песочница|action=edit}} создать] | [{{fullurl:{{FULLPAGENAME}}/песочница|action=edit&preload=Шаблон:Doc/предзагрузка-песочница}} создать] {{!}} [{{fullurl:{{FULLPAGENAME}}/песочница|action=edit&preload=Шаблон:Doc/зеркало}} зеркало] }}
}})</small> или {{#ifeq: {{NAMESPACE}}
| Модуль
| [[Модуль:Песочница|песочнице для модулей]]
| своём [[ВП:ЛП|личном пространстве]]
}}.<br>
}}
}}{{#ifexist: {{FULLPAGENAME}}/doc | Пожалуйста, добавляйте категории на подстраницу [[/doc]]. }}[[Special:PrefixIndex/{{FULLPAGENAME}}/|Подстраницы этого {{#ifeq: {{NAMESPACE}}
| Модуль
| модуля
| шаблона
}}]].
</div>
}}</includeonly><noinclude>{{doc}}</noinclude>
758a01a3d76e14ef14b2b0ee047ac47ddac8fd8e
Шаблон:Легенда
10
88
174
173
2025-01-25T21:00:34Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly><!--
--><templatestyles src="Шаблон:Легенда/styles.css" /><!--
--><span class="ts-legend {{#ifeq: {{{3|}}} | inline | ts-legend-inline }} legend" style="{{#if: {{{8|}}} | font-size: {{{8}}}; }}"><!--
--><span class="ts-legend-color legend-color mw-no-invert {{{class|}}}" style="<!--
-->{{#if: {{{4|}}} | border: {{{4}}}; | {{#if: {{{1|}}} | border: 0px solid {{{1}}};}}}}<!--
-->{{#if: {{{5|}}} | border-radius: {{{5}}};}}<!--
-->{{#if: {{{1|}}} | background: {{{1}}};}}<!--
-->{{#if: {{{6|}}} | color: {{{6}}}; }}<!--
-->" {{#if: {{{9|}}} | title="{{{9}}}" | {{#if: {{{1|}}} | title="{{{1}}}"}} }}><!--
-->{{#if: {{{alt|}}}{{{7|}}}
| <span class="ts-legend-text legend-text" style="{{#if:{{{alt|}}} | color:{{{1|}}};}}font-family: monospace, monospace;">{{#if: {{{7|}}} | {{{7}}} | }}</span>
}}<!--
--></span><!--
--> {{{2|}}}<!--
--></span><!--
--></includeonly><noinclude>
{{doc}}
<!-- Пожалуйста, добавляйте категории и интервики на страницу документации! -->
</noinclude>
362927ba47a0f5b2dcf9de3f17dbfbc8eaba4b89
Шаблон:Вложенные кавычки
10
89
176
175
2025-01-25T21:00:35Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{safesubst:<noinclude />#invoke:Вложенные кавычки|main}}<noinclude>
{{doc}}
</noinclude>
9ad9d29329e774649043f48fba384679babb4c08
Шаблон:Ombox
10
90
178
177
2025-01-25T21:00:35Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#invoke:Message box|ombox}}<noinclude>
{{doc}}<!-- Add categories and interwikis to the /doc subpage, not here! --></noinclude>
ab34435c5ebc29de589c9b059e88da5d0e6f16e4
Шаблон:Цвет/Композитор.css
10
91
180
179
2025-01-25T21:00:35Z
Vallenland
2
1 версия импортирована
text
text/plain
.infobox-above,
.infobox-header,
.infobox-below {
background: #bfe0bf;
}
@media screen {
html.skin-theme-clientpref-night .infobox-above,
html.skin-theme-clientpref-night .infobox-header {
background: #224422;
}
html.skin-theme-clientpref-night .infobox-below {
background: #182f18;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox-above,
html.skin-theme-clientpref-os .infobox-header {
background: #224422;
}
html.skin-theme-clientpref-os .infobox-below {
background: #182f18;
}
}
/*
[[Категория:Шаблоны:Подстраницы CSS]]
[[Категория:Шаблоны:Цвета по темам:Музыка|Композитор.css]]
*/
174fb6f61c3dc1ef339cd4b496da585e1c4195d6
Шаблон:Cl
10
92
182
181
2025-01-25T21:00:35Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<templatestyles src="Модуль:Template call code/styles.css" />{{#if: {{{2|}}}
| <span class="ts-templateCallCode-weak"><nowiki>[[</nowiki>Категория:[[:Категория:{{{1}}}|{{{1}}}]]<nowiki>]]</nowiki></span>
| [[:Категория:{{{1}}}|{{{1}}}]]
}}<noinclude>{{doc}}</noinclude>
3f315bb5453e2a3ef5f031e946f35c568b49f8b4
Шаблон:Docpage
10
93
184
183
2025-01-25T21:00:36Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{#ifeq: {{SUBPAGENAME}} | doc
| {{fmbox
| class = hlist nowraplinks
| style = margin-bottom:1em; background:var(--background-color-progressive-subtle, #eaf3ff); color:inherit; border:1px solid var(--border-color-content-added, #a3d3ff);
| image = [[Файл:OOjs UI icon info.svg|24px|link=|alt=|class=skin-invert-image]]
| text = <div>
* [[:{{#titleparts: {{SUBJECTPAGENAME}} | -1 }}]]
* [[:{{SUBJECTPAGENAME}}|Документация]]
* [[{{#titleparts: {{TALKPAGENAME}} | -1 }}|Обсуждение]]
* [[Служебная:Whatlinkshere/{{#titleparts: {{SUBJECTPAGENAME}} | -1 }}|Где используется]] {{#ifeq: {{NAMESPACE}} | {{ns:Template}} |
** {{Параметры шаблона|{{#titleparts: {{PAGENAME}} | -1 }}}}
}}</div><!--
-->{{#if: {{{nocat|}}} || {{#ifexist: {{NAMESPACE}}:{{BASEPAGENAME}} || [[Категория:Шаблоны:Документация несуществующих шаблонов]] }} }}
}}{{#if: {{{nocat|}}} || {{#ifeq: {{NAMESPACE}}
| Модуль
| [[Категория:Модули:Документация]]
| [[Категория:Шаблоны:Документация]]
}}__EXPECTED_UNCONNECTED_PAGE__
}}
}}</includeonly><noinclude>{{doc}}</noinclude>
e2d07566c50be35ac409e8396893a3b9d8676e0c
Шаблон:Очистить кэш
10
94
186
185
2025-01-25T21:00:36Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<!-- Класс purgelink и атрибут data-pagename используются в [[MediaWiki:Common.js]], чтобы очищать кэш без перехода на отдельную страницу --><span class="noprint purgelink" {{#if: {{{2|}}} | data-pagename="{{{2}}}" }}>{{выполнить скрипт|purgeLink}}[[Special:Purge/{{#if: {{{2|}}} | {{{2}}} | {{FULLPAGENAME}} }}|{{#if: {{{1|}}} | {{{1}}} | Очистить кэш }}]]</span>{{#ifeq: {{NAMESPACE}}{{{nocat|}}}
| {{ns:10}} <!-- Шаблон -->
| {{очищать кэш|ежедневно}}
}}<noinclude>{{doc}}</noinclude>
be6695060ca61d2125386d02d3a19109c0e7c27b
Шаблон:Установлена проверка на неизвестные параметры
10
95
188
187
2025-01-25T21:00:36Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{ombox
|name = Установлена проверка на неизвестные параметры
|text = В этом шаблоне установлена [[Модуль:Check for unknown parameters|проверка на неизвестные параметры]], добавляющая страницы в {{c|{{#if:{{{категория|}}}|{{{категория|}}}|Страницы с неизвестными параметрами шаблона {{ROOTPAGENAME}}}}|В}}.
|type = notice
}}<includeonly>{{no-doc|[[Категория:Шаблоны с установленной проверкой на неизвестные параметры]]{{#ifexist: Категория:{{#if:{{{категория|}}}|{{{категория|}}}|Страницы с неизвестными параметрами шаблона {{ROOTPAGENAME}}}} || [[Категория:Шаблоны с установленной проверкой на неизвестные параметры и несуществующей категорией]] }}|nocat={{{nocat|}}}}}</includeonly><noinclude>{{doc-inline}}
См. [[Модуль:Check for unknown parameters]] и [[:Категория:Википедия:Неизвестные параметры шаблонов]].
Добавляет {{Категория с размером|Шаблоны с установленной проверкой на неизвестные параметры и несуществующей категорией}}.
[[Категория:Шаблоны:Предупреждения]]
[[Категория:Шаблоны:Для документирования шаблонов]]
{{doc-end}}
</noinclude>
cd47e06eec53b65393adba1f3143d6cd3d6cc54c
Шаблон:C
10
96
190
189
2025-01-25T21:00:36Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#switch: {{{2}}}
| Р = {{{к|к}}}атегории
| Д = {{{к|к}}}атегории
| В = {{{к|к}}}атегорию
| Т = {{{к|к}}}атегорией
| П = {{{к|к}}}атегории
| ю = {{{к|к}}}атегорию
| ей | й = {{{к|к}}}атегорией
| и = {{{к|к}}}атегории
| {{{к|к}}}атегория
}} «[[:Категория:{{{1}}}|{{вложенные кавычки|{{{1}}}}}]]»<noinclude>{{doc}}</noinclude>
29dc241d0737db87ea05ae164b21b3bdc0da3f83
Шаблон:Цвет/Инструменталист.css
10
97
192
191
2025-01-25T21:00:37Z
Vallenland
2
1 версия импортирована
text
text/plain
.infobox-above,
.infobox-header,
.infobox-below {
background: #f4bf92;
}
@media screen {
html.skin-theme-clientpref-night .infobox-above,
html.skin-theme-clientpref-night .infobox-header,
html.skin-theme-clientpref-night .infobox-below {
background: #3f200f;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox-above,
html.skin-theme-clientpref-os .infobox-header,
html.skin-theme-clientpref-os .infobox-below {
background: #3f200f;
}
}
/*
[[Категория:Шаблоны:Подстраницы CSS]]
[[Категория:Шаблоны:Цвета по темам:Музыка|Инструменталист.css]]
*/
face7b56fa576807b9a51c764a3ac3b0f878ec82
Шаблон:OnLua
10
98
194
193
2025-01-25T21:00:37Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
#перенаправление [[Шаблон:Lua]]
b72371e7ae22239863c474a78238171c2bd94c7e
Шаблон:Музыкант/цвет/схема
10
99
196
195
2025-01-25T21:00:37Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{#switch:{{lc:{{{1|}}}}}<!--
-->|solo_singer |вокалист=Вокалист<!--
-->|non_vocal_instrumentalist |инструменталист=Инструменталист<!--
-->|non_performing_personnel |композитор |продюсер |дирижёр=Композитор<!--
-->}}</includeonly><noinclude>
{{doc}}
</noinclude>
0fc69c91f5ef446372370b02ac2ddf786f06c3d5
Шаблон:Выполнить скрипт
10
100
198
197
2025-01-25T21:00:37Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#switch: {{{1|}}}
| =
| mainPage = [[Категория:Википедия:Заглавная страница|{{NAMESPACENUMBER}}]]
| #default = {{#ifexist: Категория:Википедия:Страницы с гаджетом по требованию {{{1}}} | [[Категория:Википедия:Страницы с гаджетом по требованию {{{1}}}|{{NAMESPACENUMBER}}]] }}
}}<noinclude>
{{doc}}
</noinclude>
6979ea0342067dc76b9adcb9a5e072207c2c5a63
Шаблон:OnLua/Строка
10
101
200
199
2025-01-25T21:00:37Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
#перенаправление [[Шаблон:Lua/Строка]]
d7f869ccc7a7efc800399fce32bc75e0f91066de
Шаблон:Заготовка шаблона
10
102
202
201
2025-01-25T21:00:38Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{#invoke:TemplateDataDoc|generateBlank|{{#if:{{{1|}}}|{{{1}}}|{{BASEPAGENAME}}}}|description={{{описание|}}}}}<noinclude>{{doc}}</noinclude>
b451404244fd6898bc134564ddcb8941eca7f64a
Модуль:TemplateDataDoc
828
103
204
203
2025-01-25T21:00:38Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
require( 'strict' );
local docSubPage = mw.message.new( 'Templatedata-doc-subpage' ):plain();
local p = {};
local lastNumber = 0;
-- Enable/disable additional spacing for block-formatted templates
local formatBlockSpaces = true;
-- Params that should not be shown in code
local deprecatedParams = {
'nocat',
'from',
'nocoord',
'nocatcoord',
'Автооформление заголовка',
'автооформление заголовка',
'Ширина',
'ширина',
'Ширина изображения',
'ширина изображения',
'Ширина логотипа',
'ширина логотипа',
'Ширина автографа',
'ширина автографа',
};
local noDocNote = 'TemplateDataDoc: Запишите страницу для отображения заполненного шаблона.';
function p.processJson( json )
local status, data = pcall( mw.text.jsonDecode, json );
if status == false then
return nil;
end
if not data[ 'paramOrder' ] then
data[ 'paramOrder' ] = {};
for paramName, paramData in pairs( data[ 'params' ] ) do
table.insert( data[ 'paramOrder' ], paramName );
end
end
for _, param in ipairs( deprecatedParams ) do
if data[ 'params' ][ param ] ~= nil then
data[ 'params' ][ param ][ 'deprecated' ] = '-';
end
end
return data;
end
function p.getTemplateData( pageName )
local title = mw.title.makeTitle( 0, pageName );
if not title or not title.exists then
return false
end
local content = title:getContent()
if not content then
return false;
end;
local json = mw.ustring.match( content, '<[Tt]emplate[Dd]ata%s*>(.*)</[Tt]emplate[Dd]ata%s*>' );
if not json then
return nil;
end
return p.processJson( json )
end
function p.getValue( data, key )
if data[ key ] then
return data[ key ];
end
-- Numbered keys return as numbers
local nkey = tonumber( key );
if nkey ~= nil and data[ nkey ] then
return data[ nkey ];
end
return {};
end
-- See https://phabricator.wikimedia.org/diffusion/ETDA/browse/master/Specification.md?as=remarkup
-- We need a global format value for the 'block' and 'inline': [[phab:T205438]]
function p.convertFormatString( rawTemplateFormat )
local formatType = rawTemplateFormat or 'inline';
local templateFormat = formatType;
local isBlockFormatted = false;
if formatType == 'block' then
templateFormat = '{{_\n| _ = _\n}}';
isBlockFormatted = true;
elseif formatType == 'inline' then
templateFormat = '{{_|_=_}}';
end
return templateFormat, isBlockFormatted, formatType;
end
function p.getFormatParts( rawTemplateFormat, templateName )
local templateFormat, isBlockFormatted, formatType = p.convertFormatString( rawTemplateFormat );
local nameFormat = mw.ustring.match( templateFormat, '^[^|]+' );
local paramKeyFormat = mw.ustring.match( templateFormat, '%|[^=]+=' );
local paramValueFormat = mw.ustring.match( templateFormat, '=[^}]+' );
paramValueFormat = mw.ustring.sub( paramValueFormat, 2 );
local endFormat = mw.ustring.match( templateFormat, '%}%}.*$' );
local startFormat = mw.ustring.gsub( nameFormat, '_', templateName );
return isBlockFormatted, formatType, startFormat, endFormat, paramKeyFormat, paramValueFormat;
end
function p.formatKeyValue( key, parameterData, formatData )
if parameterData[ 'deprecated' ] then
return '';
end
local args = formatData.args;
local parameterName = key;
local nkey = tonumber( key );
-- Add additional spacing to string keys
if formatBlockSpaces and formatData.parameterLength and formatData.formatType ~= 'inline' and ( nkey == nil or lastNumber ~= nkey - 1 ) then
while mw.ustring.len( key ) < formatData.parameterLength do
key = key .. ' ';
end
end
-- Remove numbering for adjacent numbered keys
if nkey ~= nil and lastNumber == nkey - 1 then
key = '';
lastNumber = nkey;
end
local value = '';
if formatData.valueKey == 'example' and parameterData[ 'example' ] then
-- Example
value = parameterData[ 'example' ];
else
if formatData.valueKey == 'description' and parameterData[ 'description' ] then
-- Description
value = parameterData[ 'description' ];
if value ~= '' then
value = '<!-- ' .. value .. ' -->';
end
elseif parameterData[ 'autovalue' ] then
-- Autovalue
value = parameterData[ 'autovalue' ];
end
if args[ '$' .. parameterName ] and args[ '$' .. parameterName ] ~= '' then
-- Custom values from template call
value = args[ '$' .. parameterName ];
end
end
local formattedKey = mw.ustring.gsub( formatData.paramKeyFormat, '_+', key, 1 );
if key == '' then
formattedKey = mw.ustring.gsub( formattedKey, '=', '' );
end
return formattedKey .. mw.ustring.gsub( formatData.paramValueFormat, '_', value, 1 );
end
function p.generateBlankCode( templateData, templateName, args )
if templateData == false then
return '{{' .. templateName .. '}}';
end
local parameterLength = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = p.getValue( templateData[ 'params' ], parameterName );
if not parameterData[ 'deprecated' ] then
local length = mw.ustring.len( parameterName );
if length > parameterLength then
parameterLength = length;
end
end
end
local isBlockFormatted, formatType, startFormat, endFormat, paramKeyFormat, paramValueFormat = p.getFormatParts( templateData[ 'format' ], templateName );
local out = startFormat;
lastNumber = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = p.getValue( templateData[ 'params' ], parameterName );
if parameterData[ 'inherits' ] then
parameterData = p.getValue( templateData[ 'params' ], parameterData[ 'inherits' ] );
end
out = out .. p.formatKeyValue( parameterName, parameterData, {
args = args,
valueKey = ( args[ 'description' ] and 'description' or nil ),
formatType = formatType,
isBlockFormatted = isBlockFormatted,
parameterLength = parameterLength,
paramKeyFormat = paramKeyFormat,
paramValueFormat = paramValueFormat,
} );
end
return out .. endFormat;
end
function p.generateBlank( frame )
local frame = mw.getCurrentFrame();
local getArgs = require( 'Module:Arguments' ).getArgs;
local args = getArgs( frame );
local templateName = frame.args[ 1 ];
table.remove( args, 1 );
local docPage = 'Template:' .. templateName .. '/' .. docSubPage;
local templateData = p.getTemplateData( docPage );
local out = p.generateBlankCode( templateData, templateName, args );
local previewNote = ''
if templateData == false and frame:preprocess('{{REVISIONID}}') == '' then
previewNote = '<div class="warningbox">' .. noDocNote .. '</div>';
end
return previewNote .. frame:extensionTag{
name = 'syntaxhighlight',
args = { lang = 'html', copy = true },
content = out,
};
end
function p.generateExampleCode( templateData, templateName, args )
if templateData == false then
return '{{' .. templateName .. '}}';
end
local parameterLength = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = p.getValue( templateData[ 'params' ], parameterName );
if parameterData[ 'example' ] and not parameterData[ 'deprecated' ] then
local length = mw.ustring.len( parameterName );
if length > parameterLength then
parameterLength = length;
end
end
end
local isBlockFormatted, formatType, startFormat, endFormat, paramKeyFormat, paramValueFormat = p.getFormatParts( templateData[ 'format' ], templateName );
local out = startFormat;
lastNumber = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = p.getValue( templateData[ 'params' ], parameterName );
if parameterData[ 'inherits' ] then
parameterData = p.getValue( templateData[ 'params' ], parameterData[ 'inherits' ] );
end
if parameterData[ 'example' ] then
out = out .. p.formatKeyValue( parameterName, parameterData, {
args = args,
valueKey = 'example',
formatType = formatType,
isBlockFormatted = isBlockFormatted,
parameterLength = parameterLength,
paramKeyFormat = paramKeyFormat,
paramValueFormat = paramValueFormat,
} );
end
end
return out .. endFormat;
end
function p.generateExample( frame )
local frame = mw.getCurrentFrame();
local args = frame.args;
local templateName = frame.args[ 1 ];
local docPage = 'Template:' .. templateName .. '/' .. docSubPage;
local templateData = p.getTemplateData( docPage );
local out = p.generateExampleCode( templateData, templateName, args );
local previewNote = ''
if templateData == false and frame:preprocess('{{REVISIONID}}') == '' then
previewNote = '<div class="warningbox">' .. noDocNote .. '</div>';
end
return previewNote .. frame:preprocess( out ) .. frame:extensionTag{
name = 'syntaxhighlight',
args = { lang = 'html' },
content = out,
};
end
return p;
8134c68a67c62ea08db535b9110981288d627bbd
Шаблон:Старый-новый стиль,примечание
10
104
206
205
2025-01-25T21:00:39Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
В случае, если дата рождения/смерти в источниках приведена по [[Юлианский календарь|старому стилю]], рекомендуется указывать её по новому стилю, а после указать в скобках отличающуюся часть даты по старому стилю. Например,
* «13.05.1801 (1)» будет отображено как [[13 мая|1 (13) мая]] [[1801 год|1801]];
* «12.06.1801 (31.05)» будет отображено как 31 мая ([[12 июня]]) [[1801 год|1801]];
* «12.01.1802 (31.12.1801)» будет отображено как 31 декабря 1801 ([[12 января]] [[1802 год|1802]]).
При этом в статью будут автоматически подставлены категории даты рождения/смерти по ''новому'' стилю. Учтите, что разница между датами нового и старого стиля составляет 13 дней в XX и XXI веках, 12 дней в XIX веке, 11 дней в XVIII веке, 10 дней в XVII и XVI веках (начиная с 5 (15) октября 1582 года).<noinclude>{{doc-inline}}Шаблон предназначен для подстановки в качестве примечания к полям «дата рождения», «дата смерти» для страниц документации шаблонов-карточек типа «Персона».
Параметров не принимает.
Вызов: {{tl|Старый-новый стиль,примечание}} {{doc-end}} [[Категория:Википедия:Шаблоны, встраиваемые в шаблоны-карточки:Личности]]
</noinclude>
7f8754eb5c2401671df545a1cd8b315f66f86463
Шаблон:Lua
10
105
208
207
2025-01-25T21:00:39Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{ombox
| small = yes
| style = width:23em;
| image = [[Файл:Lua-logo-nolabel.svg|40px|alt=|link=]]
| text = {{replace|Этот шаблон {{#if: {{{partly|}}} | частично }} реализован на основе [[Lua]]{{#if:{{{module2|}}}{{{tech2|}}}|:<br><ul><li>}}{{#if:{{{1|}}}{{{tech|}}}| с использованием {{{tech|{{#if:{{{2|}}}|функции <code>{{#if:{{{line|}}}|[[Module:{{{1}}}#L-{{{line}}}|{{{2}}}()]]|[[{{{funcref|Module:{{{1}}}#{{{2}}}}}}|{{{2}}}()]]}}</code> из }}{{#if:{{{1|}}}|модуля [[Module:{{{1}}}|{{{1}}}]]}}}}};}}<!--
-->{{#invoke:Transclude|npc|OnLua/Строка|
module=
|function=
|tech=
|line=
}}.|;.|.}}{{#if:{{{module2|}}}{{{tech2|}}}|</ul>}} {{#if:{{{1|}}}{{{tech|}}}{{{module1|}}}{{{tech1|}}}||<div class="error"><small>'''Не указано название использующегося модуля!'''</small></div>}}
}}{{#ifeq:{{SUBPAGENAME}}|{{{doc|doc}}}||{{#if:{{{nocat|}}}||[[Категория:Шаблоны, использующие Scribunto]]{{#if:{{{1|}}}{{{tech|}}}{{{module1|}}}{{{tech1|}}}||[[Категория:Шаблоны, использующие Lua, без указания модуля]]}}}}}}</includeonly><noinclude>{{doc}}</noinclude>
f1fdaa87edb15d61e23e98f6e25d171a975e10eb
Шаблон:Музыкант/doc
10
106
210
209
2025-01-25T21:00:41Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
{{docpage}}{{OnLua|partly=1|module1=Wikidata/Interproject|module2=CategoryForProfession}}
{{Установлена проверка на неизвестные параметры}}
[[Википедия:Шаблоны-карточки|Шаблон-карточка]] {{tl|Музыкант}} должен присутствовать в начале статей о певцах, композиторах, дирижёрах и других музыкальных деятелях. Для музыкальных коллективов есть специальный шаблон {{tl|Музыкальный коллектив}}.
== Использование ==
{{Parameter names example|Фон|Имя|Оригинал имени|Изображение|Ширина|Описание изображения|Имя при рождении|Полное имя|Дата рождения|Место рождения|Дата смерти|Место смерти|Похоронен|Страна|Профессии|Годы активности|Певческий голос|Инструменты|Жанры|Псевдонимы|Коллективы|Лейбл текст|Лейблы|Награды|Логотип|Ширина логотипа|Сайт}}
{{Заготовка шаблона|$Оригинал имени = <nowiki>{{lang-XX|}}</nowiki>}}
== Описание параметров ==
# <code>Фон</code> — специализация, наиболее отражающая деятельность персоналии (см. подробности в {{tl|Музыкант/цвет}}):
::: {{Легенда|#f0e68c|'''вокалист''' — вокалист}}
::: {{Легенда|#f4bf92|'''инструменталист''' — музыкант, играющий на инструментах, но не поющий}}
::: {{Легенда|#bfe0bf|'''композитор''' — музыкант, не поющий и не играющий на инструментах (синонимы: '''дирижёр''', '''продюсер''')}}
# <code>Имя</code> — имя музыканта на русском языке.
# <code>Оригинал имени</code> — имя на официальном языке страны рождения в формате <code><nowiki>{{lang-код языка|имя}}</nowiki></code> (для русского языка — заполнять не следует).
# <code>Изображение</code> — имя файла с фотографией музыканта (см. ''[[Википедия:Иллюстрирование]]'').
# <code>Ширина</code> — ширина фото (обычно нет причины это менять).
# <code>Описание изображения</code> — где и когда сделано фото. Не сто́ит дублировать в этом поле имя музыканта: если о фотографии ничего не известно, просто не заполняйте это поле.
# <li value=7> <code>Имя при рождении</code> — следует заполнять в случае, если имя музыканта, указанное в параметре <code>Имя</code>, не принадлежало ему с рождения. Для указания полного имени нужно использовать поле <code>Полное имя</code> (''см. ниже'').</li>
# <code>Полное имя</code> — полное имя музыканта, если в поле <code>Имя</code> используется сокращённое имя.
# <code>Дата рождения</code> — дата рождения музыканта в формате дд.мм.гггг — например, <code><nowiki>31.12.1945</nowiki></code>.
# <code>Место рождения</code> — место рождения музыканта — например, <code><nowiki>{{МестоРождения|Лондон}}</nowiki></code>. Можно использовать шаблон {{tl|МестоРождения}}.
# <code>Дата смерти</code> — дата смерти музыканта в формате дд.мм.гггг (для ныне живущих, естественно, не заполняется). О датах по старому стилю см. примечание ниже.
# <code>Место смерти</code> — место смерти музыканта. Можно использовать шаблон {{tl|МестоСмерти}}.
# <code>Похоронен</code> — место захоронения музыканта.
# <code>Страна</code> — гражданство исполнителя; указывается просто название страны, без каких-либо шаблонов.
# <code>Профессии</code> — сферы музыкальной деятельности — например, <code><nowiki>{{певец|России|XX века|XXI века}}</nowiki></code>, <code><nowiki>{{поэт|России|XX века|XXI века}}</nowiki></code>
# <code>Годы активности</code> — годы активности музыканта.
# <code>Певческий голос</code> — Заполняется для оперных певцов и певиц. см. [[Певческие голоса]].
# <code>Инструменты</code> — основные музыкальные инструменты (для инструменталистов).
# <code>Жанры</code> — основные [[Список музыкальных жанров, направлений и стилей|жанры]], в которых пел/играл музыкант.
# <code>Псевдонимы</code> — [[псевдоним]]ы, под которыми известен музыкант.
# <code>Коллективы</code> — коллективы, в которых музыкант принимал участие.
# <code>Лейблы</code> — названия [[Лейбл звукозаписи|лейблов]], где издавался музыкант.
# <code>Награды</code> — государственные награды, имеющиеся у музыканта.
# <code>Логотип</code> — личный логотип музыканта (не группы, в которую он входит).
# <code>Ширина логотипа</code> — ширина логотипа (обычно нет причины это менять).
# <code>Сайт</code> — ссылка на официальный сайт музыканта.
=== Примечания ===
# Незаполненные поля не отображаются при выводе шаблона. Те из них, которые в принципе не могут быть заполнены (например, <code>Певческий голос</code> для не-певцов), нужно стирать.
# Если возникла необходимость изменить стандартные размеры фотографии, используйте параметр <code>Ширина</code>. Например, <code>{{nobr|1=Ширина = 250пкс}}</code>. Не рекомендуется использовать значения выше 300
# Шаблон автоматически добавляет включающую его статью в категории «{{cl|Музыканты по алфавиту}}» и «{{cl|Персоналии по алфавиту}}».
# Если в статье речь идёт об анонимном музыканте, известном только под псевдонимом, то в поля <code>Имя</code> записывается псевдоним.
# {{Старый-новый стиль,примечание}}
== Примеры использования ==
{| style="background: transparent; color: inherit"
|- valign="top"
|
{{Музыкант
| Имя = Иоганн Себастьян Бах
| Оригинал имени = {{lang-de|Johann Sebastian Bach}}
| Изображение = JSBach.jpg
| Описание изображения = Портрет Баха (1748)
| Фон = композитор
| Дата рождения = 21.03.1685
| Место рождения = [[Айзенах]]
| Дата смерти = 28.07.1750
| Место смерти = [[Лейпциг]]
| Страна = {{Флагификация|Германия}}
| Профессии = [[композитор]], [[органист]]
| Инструменты = [[Орган (музыкальный инструмент)|орга́н]]
| Жанры = [[классическая музыка]]
}}
|
{{Музыкант
| Имя = Джон Андерсон
| Оригинал имени = {{lang-en|Jon Anderson}}
| Изображение = Jon anderson 1977.jpg
| Описание изображения = На концерте [[Yes (группа)|Yes]] в [[Индианаполис]]е ([[1977 в музыке|1977]])
| Фон = вокалист
| Полное имя = Джон Рой Андерсон
| Дата рождения = 25.10.1944
| Место рождения = [[Аккрингтон]], [[Ланкашир]], [[Англия]]
| Страна = {{Флагификация|Великобритания}}
| Профессии = [[певец]], [[музыкант]]
| Жанры = [[прогрессивный рок]], [[нью-эйдж]]
| Коллективы = [[Yes (группа)|Yes]], [[Anderson Bruford Wakeman Howe|ABWH]], [[Jon & Vangelis]]
| Сайт = jonanderson.com
}}
|
{{Музыкант
| Имя = Джимми Пэйдж
| Оригинал имени = {{lang-en|Jimmy Page}}
| Изображение = Джимми Пэйдж.jpg
| Фон = инструменталист
| Полное имя = James Patrick Page
| Дата рождения = 09.01.1944
| Место рождения = Хестон, [[Лондон]], [[Англия]]
| Страна = {{Флагификация|Великобритания}}
| Профессии =
* [[Гитарист]]
* [[Музыкальный продюсер|продюсер]]
| Инструменты = [[Gibson Les Paul]]
* [[Gibson EDS-1275]]
* [[Danelectro 59 DC]]
* [[Fender Telecaster]]
| Жанры =
* [[хард-рок]]
* [[блюз-рок]]
* [[фолк-рок]]
* [[Прогрессивный рок|прогрессив]]
* [[хэви-метал]]
| Псевдонимы = ZoSo
| Коллективы =
* [[The Yardbirds]]
* [[Led Zeppelin]]
* [[The Honeydrippers]]
* [[The Firm]]
* [[Coverdale-Page]]
* [[Page and Plant]]
* [[XYZ (группа)|XYZ]]
| Лейблы =
* [[Swan Song]]
* [[Atlantic Records]]
| Сайт = jimmypageonline.com
}}
|}
== TemplateData ==
<templatedata>
{
"description": "Карточка для статей о певцах, композиторах, дирижёрах и других музыкальных деятелях",
"params": {
"Страна": {
"label": "Страна",
"description": "Гражданство музыканта. Указывается просто название страны, без каких-либо шаблонов; если стран несколько, они перечисляются через запятую. Может подставляться из Викиданных.",
"type": "content"
},
"Фон": {
"label": "Фон",
"description": "Цвет фона карточки. Допустимые значения: «вокалист» — вокалист; «инструменталист» — музыкант, играющий на инструментах, но не поющий; «композитор» — музыкант, не поющий и не играющий на инструментах (синонимы: «дирижёр», «продюсер»).",
"type": "line",
"suggestedvalues": [
"вокалист",
"инструменталист",
"композитор",
"дирижёр",
"продюсер"
]
},
"Имя": {
"label": "Имя",
"description": "Имя музыканта на русском языке. Если в статье речь идёт об анонимном музыканте, известном только под псевдонимом, то в поля «Имя» записывается псевдоним.",
"type": "string",
"default": "Название страницы",
"required": true
},
"Оригинал имени": {
"label": "Оригинал имени",
"description": "Имя музыканта на официальном языке страны рождения, если отличается от языка в заголовке карточки. Оборачивается в один из языковых шаблонов {{lang-XX}}.",
"example": "{{lang-de|Johann Sebastian Bach}}",
"type": "content"
},
"Изображение": {
"label": "Изображение",
"description": "Имя файла с фотографией музыканта. Может подставляться из Викиданных.",
"type": "wiki-file-name"
},
"Ширина": {
"label": "Ширина",
"description": "Ширина изображения. Не рекомендуется использовать значения выше 300.",
"type": "number"
},
"Описание изображения": {
"label": "Описание изображения",
"description": "Подпись к изображению, например где и когда сделано фото.",
"type": "line"
},
"Имя при рождении": {
"label": "Имя при рождении",
"description": "Следует заполнять в случае, если имя музыканта, указанное в параметре «Имя», не принадлежало ему с рождения.",
"type": "content"
},
"Полное имя": {
"label": "Полное имя",
"description": "Полное имя музыканта, если в поле «Имя» используется сокращённое имя.",
"type": "content"
},
"Дата рождения": {
"label": "Дата рождения",
"description": "Дата рождения музыканта в формате дд.мм.гггг, например 31.12.1945. Может подставляться из Викиданных. О датах по старому стилю см. примечание ниже.",
"type": "date"
},
"Дата смерти": {
"label": "Дата смерти",
"description": "Дата смерти музыканта в формате дд.мм.гггг (для ныне живущих, естественно, не заполняется). Может подставляться из Викиданных.",
"type": "date"
},
"Место рождения": {
"label": "Место рождения",
"description": "Место рождения музыканта — например, {{Место рождения|Лондон}}. Можно использовать шаблон {{МестоРождения}}. Может подставляться из Викиданных.",
"type": "content"
},
"Место смерти": {
"label": "Место смерти",
"description": "Место смерти музыканта. Можно использовать шаблон {{МестоСмерти}}. Может подставляться из Викиданных.",
"type": "content"
},
"Профессии": {
"label": "Профессии",
"description": "Сферы музыкальной деятельности — например, {{певец|России|XX века|XXI века}}, {{поэт|России|XX века|XXI века}}. Может подставляться из Викиданных.",
"type": "content"
},
"Годы активности": {
"label": "Годы активности",
"description": " Годы активности музыканта.",
"type": "string",
"example": "1999—2005, 2006 — {{нв}}"
},
"Певческий голос": {
"label": "Певческий голос",
"description": "Заполняется для оперных певцов и певиц.",
"type": "content"
},
"Инструменты": {
"label": "Инструменты",
"description": "Основные музыкальные инструменты (для инструменталистов).",
"type": "content"
},
"Жанры": {
"label": "Жанры",
"description": "Основные жанры, в которых пел/играл музыкант.",
"type": "content"
},
"Псевдонимы": {
"label": "Псевдонимы",
"description": "Псевдонимы, под которыми известен музыкант.",
"type": "content"
},
"Коллективы": {
"label": "Коллективы",
"description": "Коллективы, в которых музыкант принимал участие.",
"type": "content"
},
"Лейбл текст": {
"label": "Лейбл текст",
"description": "Подменяет название строки «Лейблы» на указанное.",
"type": "string"
},
"Лейблы": {
"label": "Лейблы",
"description": "Названия лейблов, где издавался музыкант.",
"type": "string"
},
"Награды": {
"label": "Награды",
"description": "Государственные награды, имеющиеся у музыканта.",
"type": "unbalanced-wikitext"
},
"Логотип": {
"label": "Логотип",
"description": "Имя файла с логотипом музыканта (не группы, в которую он входит). Может подставляться из Викиданных.",
"type": "wiki-file-name"
},
"Ширина логотипа": {
"label": "Ширина логотипа",
"description": "Ширина логотипа. Не рекомендуется использовать значения выше 300.",
"type": "number"
},
"Сайт": {
"label": "Сайт",
"description": "Ссылка на официальный сайт музыканта. Может подставляться из Викиданных.",
"type": "url"
},
"Викисклад": {
"label": "Викисклад",
"description": "Ссылка на категорию о музыканте на Викискладе. Может подставляться из Викиданных.",
"type": "line",
"deprecated": "Заполняется автоматически из Викиданных"
},
"Викитека": {
"label": "Викитека",
"type": "string",
"deprecated": "Заполнятся автоматически из Викиданных"
},
"Похоронен": {
"description": "Место, где похоронен музыкант.",
"type": "line"
},
"from": {
"type": "line"
},
"nocat": {
"type": "boolean",
"autovalue": "1"
}
},
"format": "{{_\n| ________________ = _\n}}\n",
"paramOrder": [
"Фон",
"Имя",
"Оригинал имени",
"Изображение",
"Ширина",
"Описание изображения",
"Имя при рождении",
"Полное имя",
"Дата рождения",
"Место рождения",
"Дата смерти",
"Место смерти",
"Похоронен",
"Страна",
"Профессии",
"Годы активности",
"Певческий голос",
"Инструменты",
"Жанры",
"Псевдонимы",
"Коллективы",
"Лейбл текст",
"Лейблы",
"Награды",
"Логотип",
"Ширина логотипа",
"Сайт",
"Викисклад",
"Викитека",
"from",
"nocat"
]
}
</templatedata>
== См. также ==
* {{tl|Музыкальный коллектив}}
* {{tl|Навигационная таблица музыкального исполнителя}}
* {{cl|Шаблоны-карточки:Личности|1}}
<includeonly>
[[Категория:Шаблоны:Музыканты]]
[[Категория:Шаблоны-карточки:Профессии культуры и искусства]]
[[Категория:Шаблоны-карточки:Музыка]]
</includeonly>
14ba03f3c4d9c6ee2c17a8274508fb62ce0dfa32
Шаблон:Пример с именами параметров
10
107
212
211
2025-01-25T21:00:41Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{#invoke:Parameter names example|main}}</includeonly><noinclude>
{{Doc}}
</noinclude>
2118cbf70aef4a440190a91ba85327a5cb8d3808
Модуль:Parameter names example
828
108
214
213
2025-01-25T21:00:42Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
-- This module implements {{parameter names example}}.
local p = {}
local function makeParam(s)
local lb = '{'
local rb = '}'
return lb:rep(3) .. s .. rb:rep(3)
end
local function italicize(s)
return "''" .. s .. "''"
end
local function plain(s)
return s
end
function p._main(args, frame)
-- Find how we want to format the arguments to the template.
local formatFunc
if args._display == 'italics' or args._display == 'italic' then
formatFunc = italicize
elseif args._display == 'plain' then
formatFunc = plain
else
formatFunc = makeParam
end
-- Build the table of template arguments.
local targs = {}
for k, v in pairs(args) do
if type(k) == 'number' then
targs[v] = formatFunc(v)
elseif not k:find('^_') then
targs[k] = v
end
end
-- Find the template name.
local template
if args._template then
template = args._template
else
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.prefixedText:find('/sandbox$') or currentTitle.prefixedText:find('/песочница$') then
template = currentTitle.prefixedText
else
template = currentTitle.basePageTitle.prefixedText
end
end
-- Call the template with the arguments.
frame = frame or mw.getCurrentFrame()
local success, result = pcall(
frame.expandTemplate,
frame,
{title = template, args = targs}
)
if success then
return result
else
return ''
end
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Шаблон:Пример с именами параметров'
})
return p._main(args, frame)
end
return p
64667ee447347f717db659027d7c4ec864230a93
Шаблон:Parameter names example
10
109
216
215
2025-01-25T21:00:42Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
#перенаправление [[Шаблон:Пример с именами параметров]]
f42e4b1940da05c9e876c1c77cffa5c78e59c68d
Шаблон:Легенда/styles.css
10
110
218
217
2025-01-25T21:00:42Z
Vallenland
2
1 версия импортирована
text
text/plain
/* Скопировано из [[:en:Template:Legend/styles.css]] с изменениями */
.ts-legend {
page-break-inside: avoid;
break-inside: avoid-column;
display: block;
font-size: 90%;
}
.thumb .ts-legend,
figcaption .ts-legend {
font-size: inherit;
}
.ts-legend-inline {
display: inline-block;
}
.ts-legend-color {
display: inline-block;
min-width: 1.25em;
height: 1.25em;
line-height: 1.25;
margin: 1px 0;
text-align: center;
border: 1px solid black;
color: black;
vertical-align: middle;
}
/*empty for now, but part of the design!*/
/*.ts-legend-text {}*/
/* [[Категория:Шаблоны:Подстраницы CSS]] */
92f4aefe4d4206899f554e9262090e50a27a5171
Модуль:Message box/ombox.css
828
111
220
219
2025-01-25T21:00:42Z
Vallenland
2
1 версия импортирована
text
text/plain
/* Скопировано из [[:en:Module:Message box/ombox.css]] */
.ombox {
margin: 4px 0;
border-collapse: collapse;
border: 1px solid var(--border-color-base, #a2a9b1); /* Default "notice" gray */
background-color: var(--background-color-neutral-subtle, #f8f9fa);
box-sizing: border-box;
}
/* For the "small=yes" option. */
.ombox.mbox-small {
font-size: 88%;
line-height: 1.25em;
}
.ombox-speedy {
border: 2px solid var(--border-color-error, #b32424); /* Red */
background-color: var(--background-color-error-subtle, #fee7e6); /* Pink */
}
.ombox-delete {
border: 2px solid var(--background-color-error--active, #b32424); /* Red */
}
.ombox-content {
border: 1px solid #f28500; /* Orange */
}
.ombox-style {
border: 1px solid #fc3; /* Yellow */
}
.ombox-move {
border: 1px solid #9932cc; /* Purple */
}
.ombox-protection {
border: 2px solid var(--border-color-base, #a2a9b1); /* Gray-gold */
}
.ombox .mbox-text {
border: none;
/* @noflip */
padding: 0.25em 0.9em;
width: 100%;
}
.ombox .mbox-image {
border: none;
/* @noflip */
padding: 2px 0 2px 0.9em;
text-align: center;
}
.ombox .mbox-imageright {
border: none;
/* @noflip */
padding: 2px 0.9em 2px 0;
text-align: center;
}
/* An empty narrow cell */
.ombox .mbox-empty-cell {
border: none;
padding: 0;
width: 1px;
}
.ombox .mbox-invalid-type {
text-align: center;
}
/* Хак, TODO: посмотреть, как оно на самом деле работает */
.ombox .mbox-textsmall-div {
font-size: 90%;
}
@media (min-width: 720px) {
.ombox {
margin: 4px 10%;
}
.ombox.mbox-small {
/* @noflip */
clear: right;
/* @noflip */
float: right;
/* @noflip */
margin: 4px 0 4px 1em;
width: 238px;
}
/* Стили нотификаций для ноутбуков */
@media (max-width: 1366px) {
.ombox {
margin-left: 6%;
margin-right: 6%;
}
}
}
/* [[Категория:Модули:Подстраницы CSS]] */
6627874170f6674674bfa5796b2f7dfb6698cd81
Шаблон:Lua/Строка
10
112
222
221
2025-01-25T21:00:42Z
Vallenland
2
1 версия импортирована
wikitext
text/x-wiki
<includeonly>{{#if: {{{module|}}}{{{tech|}}} | <li>с использованием {{#if: {{{tech|}}} | {{{tech}}} | {{#if: {{{function|}}} | {{#if: {{{module|}}} | функции <code>{{#if: {{{line|}}} | [{{fullurl: Module:{{{module}}}|action=edit}}#mw-ce-l{{{line}}} {{{function}}}()] | [[{{{funcref|Module:{{{module}}}#{{{function}}}}}} | {{{function}}}()]]}}</code> из }}}}{{#if: {{{module|}}} | модуля [[Module:{{{module}}} | {{{module}}}]]}}}};}}</includeonly><noinclude>[[Категория:Шаблоны:Подстраницы шаблонов]]</noinclude>
5a35837338c2daee2d240a8e5335e8fec8e7d87e
Модуль:Вложенные кавычки
828
113
224
223
2025-01-25T21:00:43Z
Vallenland
2
1 версия импортирована
Scribunto
text/plain
--
-- Re-implement [[Template:Вложенные кавычки]] in Lua
-- Replaces «» to „“ without touching links
--
require( 'strict' )
local getArgs
local p = {}
local function isEmpty( str )
return str == nil or str == ''
end
local function protectLinks( str )
local links, head = {}, 0
while true do
local s, e, link = str:find( '(%[%[.-%]%])', head )
if not link then
return str, links
elseif link:find( '[[', 3, true ) then
head = s + 2
else
-- If the alt text contains '[', it can have one final ']'.
if link:match( '^[^|]*|.-%[', 3 ) and str:sub( e + 1, e + 1 ) == ']' then
link = link .. ']'
end
table.insert( links, link )
local placeholder = mw.ustring.char( 0xF0000 + #links )
str = str:gsub( link:gsub( '[$%%()*+%-.?[%]^]', '%%%0' ), placeholder )
head = str:find( placeholder ) + 1
end
end
end
local function unprotectLinks( str, links )
for i, link in ipairs( links ) do
str = str:gsub( mw.ustring.char( 0xF0000 + i ), link:gsub( '%%', '%%%%' ), 1 )
end
return str
end
local function replace( str )
if isEmpty( str ) then
return ''
end
str = mw.ustring.gsub( str, '«(.[^«»]-)»', '„%1“' )
return str
end
function p._main( text )
if isEmpty( text ) then
return ''
end
local links = {}
text, links = protectLinks( text )
if #links == 0 then
return replace( text )
end
-- Replace visible link text while keeping links intact
for i, link in ipairs( links ) do
local linkTarget = mw.text.trim( link, '%[%]' )
local linkText = ''
local pipePos = link:find( '|', 1, true )
if pipePos ~= nil then
local parts = mw.text.split( linkTarget, '|' )
linkTarget = parts[ 1 ]
linkText = replace( parts[ 2 ] )
else
linkText = replace( linkTarget )
end
links[ i ] = string.format( '[[%s|%s]]', linkTarget, linkText )
end
text = replace( text )
text = unprotectLinks( text, links )
return text
end
function p.main( frame )
getArgs = require( 'Module:Arguments' ).getArgs
local args = getArgs( frame )
return p._main( args[ 1 ] )
end
return p
e7cf7cd583a5fa189c85ccf455feebd48aa60fa0
Шаблон:Инфобокс
10
114
225
2025-01-26T18:30:52Z
Vallenland
2
Новая страница: «{| class="wikitable" style="float: right" | colspan="2" |Заголовок |- |Ячейка |Значение |- | colspan="2" |<nowiki>[[Foto1.png]]</nowiki> |} <nowiki> {| class="wikitable" style="float: right" | colspan="2" |Заголовок |- |Ячейка |Значение |- | colspan="2" |<nowiki>[[Foto1.png]]</nowiki> |} </nowiki>»
wikitext
text/x-wiki
{| class="wikitable" style="float: right"
| colspan="2" |Заголовок
|-
|Ячейка
|Значение
|-
| colspan="2" |<nowiki>[[Foto1.png]]</nowiki>
|}
<nowiki>
{| class="wikitable" style="float: right"
| colspan="2" |Заголовок
|-
|Ячейка
|Значение
|-
| colspan="2" |<nowiki>[[Foto1.png]]</nowiki>
|}
</nowiki>
448320f4fb2d0f654a4f9b671997e837b1666b45
226
225
2025-01-26T18:32:09Z
Vallenland
2
wikitext
text/x-wiki
{| class="wikitable" style="float: right"
| colspan="2" |Отсюда и поехали
|}
5f1a9449dfb0c1ca6fde14db09617e9ab85fe1ce
227
226
2025-01-26T18:33:09Z
Vallenland
2
wikitext
text/x-wiki
<nowiki>{| class="wikitable" style="float: right"</nowiki>
| colspan="2" |Отсюда и поехали
|}
{| class="wikitable" style="float: right"
| colspan="2" |Отсюда и поехали
|}
ЭТОТ ШАБЛОН ИСКЛЮЧИТЕЛЬНО ДЛЯ КОПИРОВАНИЯ КОДА ТАБЛИЦЫ И ПЕРЕДЕЛКИ ЕЁ В ВИЗУАЛЬНОМ РЕДАКТОРЕ! НЕ НУЖНО ЕГО ВСТАВЛЯТЬ НА СТРАНИЦУ!
1a542d10d6b3b1847fb9a2fc43492f4ff1444e62
Шаблон:Страна
10
115
228
2025-01-26T18:36:17Z
Vallenland
2
Новая страница: «{| class="wikitable" style="float: right" | colspan="2" |Отсюда и поехали |}»
wikitext
text/x-wiki
{| class="wikitable" style="float: right"
| colspan="2" |Отсюда и поехали
|}
fb618423e55eaa49a357a6a24db2e78a0c42fba0
229
228
2025-01-26T20:05:24Z
Vallenland
2
wikitext
text/x-wiki
{| class="wikitable" style="float: right"
| colspan="2" |<center>'''{{{название}}}'''
{{{другое_название}}}
|-
|<center>[[Файл:{{{флаг}}}.png|100px]]
|<center>[[Файл:{{{герб}}}.png|100px]]
|-
| colspan="2" |<center>[[Файл:{{{фотография}}}|300px]]
|-
| colspan="2" |<center>{{{гимн}}}
|-
| colspan="2" |<center>{{{карта}}}
|-
|'''Язык(и)'''
|{{{язык}}}
|-
|'''Столица'''
|{{{столица}}}
|-
|'''Форма правления'''
|{{{форма_правления}}}
|-
|'''Идеология'''
|{{{идеология}}}
|-
|'''{{{глава}}}'''
|{{{имя_главы}}}
|-
|'''Гос. религия'''
|{{{религия}}}
|-
|'''Территория'''
|{{{территория}}}
|-
|'''Население'''
|{{{население}}}
|-
|'''Катойконимы'''
|{{{названия_жителей}}}
|-
|'''Валюта'''
|{{{валюта}}}
|-
|'''Домен'''
|{{{домен}}}
|}
4b0f423cd5aa00a894951640b19603b7d1d448aa
236
229
2025-01-26T21:50:48Z
Vallenland
2
wikitext
text/x-wiki
{| class="wikitable" style="float: right"
| colspan="2" |<center>'''<big>{{{название}}}</big>'''
{{{другое_название}}}
|-
|<center>[[Файл:{{{флаг}}}.png|100px]]
<nowiki>{{{описфлага}}}</nowiki>
|<center>[[Файл:{{{герб}}}.png|100px]]
<nowiki>{{{описгерба}}}</nowiki>
|-
| colspan="2" |<center>[[Файл:{{{фотография}}}|300px]]
|-
| colspan="2" |<center>{{{гимн}}}
|-
| colspan="2" |<center>{{{карта}}}
|-
|'''Язык(и)'''
|{{{язык}}}
|-
|'''Столица'''
|{{{столица}}}
|-
|'''Форма правления'''
|{{{форма_правления}}}
|-
|'''Идеология'''
|{{{идеология}}}
|-
|'''{{{глава}}}'''
|{{{имя_главы}}}
|-
|'''Гос. религия'''
|{{{религия}}}
|-
|'''Территория'''
|{{{территория}}}
|-
|'''Население'''
|{{{население}}}
|-
|'''Катойконимы'''
|{{{названия_жителей}}}
|-
|'''Валюта'''
|{{{валюта}}}
|-
|'''Домен'''
|{{{домен}}}
|}
858e3b60a8c7f4946d7015c94b5e0c460268e197
238
236
2025-01-26T21:52:41Z
Vallenland
2
wikitext
text/x-wiki
{| class="wikitable" style="float: right"
| colspan="2" |<center>'''<big>{{{название}}}</big>'''
{{{другое_название}}}
|-
|<center>[[Файл:{{{флаг}}}.png|100px]]
{{{описфлага}}}
|<center>[[Файл:{{{герб}}}.png|100px]]
{{{описгерба}}}
|-
| colspan="2" |<center>[[Файл:{{{фотография}}}|300px]]
|-
| colspan="2" |<center>{{{гимн}}}
|-
| colspan="2" |<center>{{{карта}}}
|-
|'''Язык(и)'''
|{{{язык}}}
|-
|'''Столица'''
|{{{столица}}}
|-
|'''Форма правления'''
|{{{форма_правления}}}
|-
|'''Идеология'''
|{{{идеология}}}
|-
|'''{{{глава}}}'''
|{{{имя_главы}}}
|-
|'''Гос. религия'''
|{{{религия}}}
|-
|'''Территория'''
|{{{территория}}}
|-
|'''Население'''
|{{{население}}}
|-
|'''Катойконимы'''
|{{{названия_жителей}}}
|-
|'''Валюта'''
|{{{валюта}}}
|-
|'''Домен'''
|{{{домен}}}
|}
af50a2b64c791b0f9baeeef48e681c15cb091e1c
Файл:Flag of Vallenland.png
6
116
230
2025-01-26T21:11:11Z
Vallenland
2
wikitext
text/x-wiki
s
a0f1490a20d0211c997b44bc357e1972deab8ae3
Файл:Центр Валленланда.png
6
117
231
2025-01-26T21:14:48Z
Vallenland
2
wikitext
text/x-wiki
ы
5e6c96299a2f11e9b4f77ffc8c712ecd5da70df6
Файл:Sputnik map of Vallenland.png
6
118
232
2025-01-26T21:21:19Z
Vallenland
2
wikitext
text/x-wiki
j
5c2dd944dde9e08881bef0894fe7b22a5c9c4b06
Валленланд
0
4
233
7
2025-01-26T21:23:16Z
Vallenland
2
wikitext
text/x-wiki
{{Страна|название=Валленланд|другое_название=Валленландская севастократия|флаг=Flag of Vallenland|фотография=Центр Валленланда.png|гимн=[[Гимн Валленланда|"Крылатые качели"]]|язык=русский|столица=отсутствует|форма_правления=севастократия (королевство)|идеология=нелиберальная социал-демократия|глава=Севастократор|имя_главы=Макар Григорьев|религия=агностицизм|территория=4 060 кв.м|население=1 человек|названия_жителей=валленландцы, валленландец, валленляндка|валюта=рубль (планируется)|домен=.vl|карта=[[Файл:Sputnik map of Vallenland.png|300px]]
Спутниковая карта Валленланда. Жёлтым выделена государственная
граница севастократии.}}
'''Валленланд''' (официально '''Валленландская Севастократия''', допускается также написание '''Валенланд''' и '''Валенландская Севастократия''') - микрогосударство на части зелёной территории города Пскова Псковской области. Официально [[Международное признание Валленланда|признан]] макрогосударствами как территория, принадлежащая Российской Федерации. Территории Валленланда расположены к востоку от 4-го многопрофильного лицея города Пскова. Они периодически контролируются то Валленлендом, то Россией. Площадь этих территорий, по измерениям Google Maps, составляет 4060 м<small><sup>2</sup></small> (0,406 га).
Непостоянное [[Население Валленланда|население]] Валленланда составляет 1 человека, который и является правителем данного микрогосударства. По национальности он - цыган, следовательно, 100% населения Валленланда составляют цыгане. [[Мандат о независимости Валленланда|Мандатом о независимости]] от [[Национальный день принятия мандата о независимости Валленланда|22 января 2025 года]] установлены также полностью открытые границы и отсутствие государственного контроля за ними. В связи с этим через территорию Валленланда (чаще всего транзитом) проходят несколько десятков человек в день.
Столица, равно как и административно-территориальное устройство, у Валленландской Севастократии отсутствует в связи со слишком маленькой площадью для необходимости этого. Из-за этого Валленланд можно отнести к сверхунитарным микрогосударствам.
Валленланд имеет всего лишь одну общую границу с Российской Федерацией длиной в 453 м. Денежной единицы в силу временной нецелесообразности её введения (слишком малое число граждан) Валленланд не имеет. В противном случае денежной единицей станет российский рубль.
Валленландская Севастократия долго находилась под властью многих государств - от Киевской Руси до Российской Федерации. Полный перечень всех стран, которые включали её в свой состав: Киевская Русь, Новгородская Республика, Псковская земля (позже - фактически под властью России), Русское государство, Российская империя, Эстония, Российская Советская Федеративная Социалистическая Республика, Великогерманский Рейх, вновь РСФСР и Российская Федерация. Независимый Валленланд появился 22 января 2025 года.
Во главе Валленланда стоит [[Севастократор Валленланда|севастократор]] (до этого севастократором был высший придворный Византии, тем не менее, примерно соответствующий королю), имеющий абсолютную власть в стране до тех пор, пока не будет написана и принята первая [[конституция Валленланда]]. На 2025 год этот титул принадлежит [[Макар Григорьев|Макару Григорьеву]].
60e947894cefc9d8765f0bbbe6cce97c8562bd6a
235
233
2025-01-26T21:49:02Z
Vallenland
2
wikitext
text/x-wiki
{{Страна|название=Валленланд|другое_название=Валленландская севастократия|флаг=Flag of Vallenland|фотография=Центр Валленланда.png|гимн=[[Гимн Валленланда|"Крылатые качели"]]|язык=русский|столица=отсутствует|форма_правления=севастократия (королевство)|идеология=нелиберальная социал-демократия|глава=Севастократор|имя_главы=Макар Григорьев|религия=агностицизм|территория=4 060 кв.м|население=1 человек|названия_жителей=валленландцы, валленландец, валленляндка|валюта=рубль (планируется)|домен=.vl|карта=[[Файл:Sputnik map of Vallenland.png|300px]]
Спутниковая карта Валленланда. Жёлтым выделена государственная
граница севастократии.|герб=VVV}}
'''Валленланд''' (официально '''Валленландская Севастократия''', допускается также написание '''Валенланд''' и '''Валенландская Севастократия''') - микрогосударство на части зелёной территории города Пскова Псковской области. Официально [[Международное признание Валленланда|признан]] макрогосударствами как территория, принадлежащая Российской Федерации. Территории Валленланда расположены к востоку от 4-го многопрофильного лицея города Пскова. Они периодически контролируются то Валленлендом, то Россией. Площадь этих территорий, по измерениям Google Maps, составляет 4060 м<small><sup>2</sup></small> (0,406 га).
Непостоянное [[Население Валленланда|население]] Валленланда составляет 1 человека, который и является правителем данного микрогосударства. По национальности он - цыган, следовательно, 100% населения Валленланда составляют цыгане. [[Мандат о независимости Валленланда|Мандатом о независимости]] от [[Национальный день принятия мандата о независимости Валленланда|22 января 2025 года]] установлены также полностью открытые границы и отсутствие государственного контроля за ними. В связи с этим через территорию Валленланда (чаще всего транзитом) проходят несколько десятков человек в день.
Столица, равно как и административно-территориальное устройство, у Валленландской Севастократии отсутствует в связи со слишком маленькой площадью для необходимости этого. Из-за этого Валленланд можно отнести к сверхунитарным микрогосударствам.
Валленланд имеет всего лишь одну общую границу с Российской Федерацией длиной в 453 м. Денежной единицы в силу временной нецелесообразности её введения (слишком малое число граждан) Валленланд не имеет. В противном случае денежной единицей станет российский рубль.
Валленландская Севастократия долго находилась под властью многих государств - от Киевской Руси до Российской Федерации. Полный перечень всех стран, которые включали её в свой состав: Киевская Русь, Новгородская Республика, Псковская земля (позже - фактически под властью России), Русское государство, Российская империя, Эстония, Российская Советская Федеративная Социалистическая Республика, Великогерманский Рейх, вновь РСФСР и Российская Федерация. Независимый Валленланд появился 22 января 2025 года.
Во главе Валленланда стоит [[Севастократор Валленланда|севастократор]] (до этого севастократором был высший придворный Византии, тем не менее, примерно соответствующий королю), имеющий абсолютную власть в стране до тех пор, пока не будет написана и принята первая [[конституция Валленланда]]. На 2025 год этот титул принадлежит [[Макар Григорьев|Макару Григорьеву]].
3051f9345e4a37f8b067c368dbcb5d08a3e1eaab
237
235
2025-01-26T21:52:12Z
Vallenland
2
wikitext
text/x-wiki
{{Страна|название=Валленланд|другое_название=Валленландская севастократия|флаг=Flag of Vallenland|фотография=Центр Валленланда.png|гимн=[[Гимн Валленланда|"Крылатые качели"]]|язык=русский|столица=отсутствует|форма_правления=севастократия (королевство)|идеология=нелиберальная социал-демократия|глава=Севастократор|имя_главы=Макар Григорьев|религия=агностицизм|территория=4 060 кв.м|население=1 человек|названия_жителей=валленландцы, валленландец, валленляндка|валюта=рубль (планируется)|домен=.vl|карта=[[Файл:Sputnik map of Vallenland.png|300px]]
Спутниковая карта Валленланда. Жёлтым выделена государственная
граница севастократии.|герб=VVV|описфлага=Флаг Валленланда|описгерба=Национальная эмблема Валленланда}}
'''Валленланд''' (официально '''Валленландская Севастократия''', допускается также написание '''Валенланд''' и '''Валенландская Севастократия''') - микрогосударство на части зелёной территории города Пскова Псковской области. Официально [[Международное признание Валленланда|признан]] макрогосударствами как территория, принадлежащая Российской Федерации. Территории Валленланда расположены к востоку от 4-го многопрофильного лицея города Пскова. Они периодически контролируются то Валленлендом, то Россией. Площадь этих территорий, по измерениям Google Maps, составляет 4060 м<small><sup>2</sup></small> (0,406 га).
Непостоянное [[Население Валленланда|население]] Валленланда составляет 1 человека, который и является правителем данного микрогосударства. По национальности он - цыган, следовательно, 100% населения Валленланда составляют цыгане. [[Мандат о независимости Валленланда|Мандатом о независимости]] от [[Национальный день принятия мандата о независимости Валленланда|22 января 2025 года]] установлены также полностью открытые границы и отсутствие государственного контроля за ними. В связи с этим через территорию Валленланда (чаще всего транзитом) проходят несколько десятков человек в день.
Столица, равно как и административно-территориальное устройство, у Валленландской Севастократии отсутствует в связи со слишком маленькой площадью для необходимости этого. Из-за этого Валленланд можно отнести к сверхунитарным микрогосударствам.
Валленланд имеет всего лишь одну общую границу с Российской Федерацией длиной в 453 м. Денежной единицы в силу временной нецелесообразности её введения (слишком малое число граждан) Валленланд не имеет. В противном случае денежной единицей станет российский рубль.
Валленландская Севастократия долго находилась под властью многих государств - от Киевской Руси до Российской Федерации. Полный перечень всех стран, которые включали её в свой состав: Киевская Русь, Новгородская Республика, Псковская земля (позже - фактически под властью России), Русское государство, Российская империя, Эстония, Российская Советская Федеративная Социалистическая Республика, Великогерманский Рейх, вновь РСФСР и Российская Федерация. Независимый Валленланд появился 22 января 2025 года.
Во главе Валленланда стоит [[Севастократор Валленланда|севастократор]] (до этого севастократором был высший придворный Византии, тем не менее, примерно соответствующий королю), имеющий абсолютную власть в стране до тех пор, пока не будет написана и принята первая [[конституция Валленланда]]. На 2025 год этот титул принадлежит [[Макар Григорьев|Макару Григорьеву]].
229a3d543083c03c941f37f0350e1e8b3612a6df
240
237
2025-01-26T22:09:45Z
Vallenland
2
wikitext
text/x-wiki
{{Страна|название=Валленланд|другое_название=Валленландская севастократия|флаг=Flag of Vallenland|фотография=Центр Валленланда.png|гимн=[[Гимн Валленланда|"Крылатые качели"]]|язык=русский|столица=отсутствует|форма_правления=севастократия (королевство)|идеология=нелиберальная социал-демократия|глава=Севастократор|имя_главы=Макар Григорьев|религия=агностицизм|территория=4 060 кв.м|население=1 человек|названия_жителей=валленландцы, валленландец, валленляндка|валюта=рубль (планируется)|домен=.vl|карта=[[Файл:Sputnik map of Vallenland.png|300px]]
Спутниковая карта Валленланда. Жёлтым выделена государственная
граница севастократии.|герб=VVV|описфлага=Флаг Валленланда|описгерба=Национальная эмблема Валленланда}}
'''Валленланд''' (официально '''Валленландская Севастократия''', допускается также написание '''Валенланд''' и '''Валенландская Севастократия''') - микрогосударство на части зелёной территории города Пскова Псковской области. Официально [[Международное признание Валленланда|признан]] макрогосударствами как территория, принадлежащая Российской Федерации. Территории Валленланда расположены к востоку от 4-го многопрофильного лицея города Пскова. Они периодически контролируются то Валленлендом, то Россией. Площадь этих территорий, по измерениям Google Maps, составляет 4060 м<small><sup>2</sup></small> (0,406 га).
Непостоянное [[Население Валленланда|население]] Валленланда составляет 1 человека, который и является правителем данного микрогосударства. По национальности он - цыган, следовательно, 100% населения Валленланда составляют цыгане. [[Мандат о независимости Валленланда|Мандатом о независимости]] от [[Национальный день принятия мандата о независимости Валленланда|22 января 2025 года]] установлены также полностью открытые границы и отсутствие государственного контроля за ними. В связи с этим через территорию Валленланда (чаще всего транзитом) проходят несколько десятков человек в день.
Столица, равно как и административно-территориальное устройство, у Валленландской Севастократии отсутствует в связи со слишком маленькой площадью для необходимости этого. Из-за этого Валленланд можно отнести к сверхунитарным микрогосударствам.
Валленланд имеет всего лишь одну общую границу с Российской Федерацией длиной в 453 м. Денежной единицы в силу временной нецелесообразности её введения (слишком малое число граждан) Валленланд не имеет. В противном случае денежной единицей станет российский рубль.
Валленландская севастократия долго находилась под властью многих государств - от Киевской Руси до Российской Федерации. Полный перечень всех стран, которые включали её в свой состав: Киевская Русь, Новгородская Республика, Псковская земля (позже - фактически под властью России), Русское государство, Российская империя, Эстония, Российская Советская Федеративная Социалистическая Республика, Великогерманский Рейх, вновь РСФСР и Российская Федерация. Независимый Валленланд появился 22 января 2025 года.
Во главе Валленланда стоит [[Севастократор Валленланда|севастократор]] (до этого севастократором был высший придворный Византии, тем не менее, примерно соответствующий королю), имеющий абсолютную власть в стране до тех пор, пока не будет написана и принята первая [[конституция Валленланда]]. На 2025 год этот титул принадлежит [[Макар Григорьев|Макару Григорьеву]].
== Этимология ==
До создания микронации наименование "Валленланд" нигде особо не использовалось, за исключением виртуального государства в NationStates, которое не имеет никакого отношения к микронации Валленланд. Название для этой территории было установлено Мандатом о независимости, где сказано, что "отныне землю к западу от дома 26-го по улице Коммунальной до дороги к востоку от 4-м многопрофильного лицея, от дома 28-го по улице Коммунальной до тропы, ведущей к Рижскому проспекту, впредь именовать "Валленланд". Такое название было выбрано из-за того, что на немецком "wollen" означает "хотеть", а "land" - страна. Дословно другими словами - "страна, которую мы желаем".
fb6c24043a566348786118bd8b5f62dbecf51c8c
Файл:VVV.png
6
119
234
2025-01-26T21:48:34Z
Vallenland
2
wikitext
text/x-wiki
vvv
dbe6cae2f52b55095b513c15321b934146828d76
Заглавная страница
0
1
239
6
2025-01-26T21:54:26Z
Vallenland
2
wikitext
text/x-wiki
__NOTOC__
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center;">[[Файл:Vallenbox (greeting).png|центр|безрамки|160x160пкс]]<big>'''Добро пожаловать на Валленланд Вики, энциклопедию о микрогосударстве Валленланд.'''</big>
Валленланд - микрогосударство на части территории города Пскова одноимённой области в России. Оно было основано в 2025 году и активно развивается.
</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Статьи, которые следует прочитать...'''
[[Справка:Что такое Валленланд|Простым людям]]ㅤㅤ [[Справка:Как доказать гражданство для вики|Гражданам Валленланда]]ㅤㅤ [[Справка:Установка дипломатических отношений|Главам микронаций]]
[[Справка:Как получить гражданство|Желающим получить гражданство Валленланда]]</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Избранная статья'''
'''Валленланд''' (официально '''Валленландская Севастократия''', допускается также написание '''Валенланд''' и '''Валенландская Севастократия''') - микрогосударство на части зелёной территории города Пскова Псковской области. Официально [[Международное признание Валленланда|признан]] макрогосударствами как территория, принадлежащая Российской Федерации. Территории Валленланда расположены к востоку от 4-го многопрофильного лицея города Пскова. Они периодически контролируются то Валленлендом, то Россией. Площадь этих территорий, по измерениям Google Maps, составляет 4060 м<small><sup>2</sup></small> (0,406 га).
[[Валленланд|Читать далее...]]
</div>
7ef86bcc2f6044e5862882a5b24da368d541833e
241
239
2025-01-26T22:10:12Z
Vallenland
2
wikitext
text/x-wiki
__NOTOC__
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center;">[[Файл:Vallenbox (greeting).png|центр|безрамки|160x160пкс]]<big>'''Добро пожаловать на Валленланд Вики, энциклопедию о микрогосударстве Валленланд.'''</big>
Валленланд - микрогосударство на части территории города Пскова одноимённой области в России. Оно было основано в 2025 году и активно развивается.
</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Статьи, которые следует прочитать...'''
[[Справка:Что такое Валленланд|Простым людям]]ㅤㅤ [[Справка:Как доказать гражданство для вики|Гражданам Валленланда]]ㅤㅤ [[Справка:Установка дипломатических отношений|Главам микронаций]]
[[Справка:Как получить гражданство|Желающим получить гражданство Валленланда]]</div>
<div style="border: solid black; background: rgb(100,100,100);
background: radial-gradient(circle, rgba(127,201,255,1) 50%, rgba(82,127,63,1) 100%); color: white; text-align: center; flex: 1; margin: 2px;
display: block;">'''Избранная статья'''
'''Валленланд''' (официально '''Валленландская Севастократия''', допускается также написание '''Валенланд''' и '''Валенландская Севастократия''') - микрогосударство на части зелёной территории города Пскова Псковской области. Официально признан макрогосударствами как территория, принадлежащая Российской Федерации. Территории Валленланда расположены к востоку от 4-го многопрофильного лицея города Пскова. Они периодически контролируются то Валленлендом, то Россией. Площадь этих территорий, по измерениям Google Maps, составляет 4060 м<small><sup>2</sup></small> (0,406 га).
[[Валленланд|Читать далее...]]
</div>
3d3012a9cc8865fcf50f11a0d617711a0f5b4810